Android之一问一答

142 阅读8分钟

1.数据库的操作类型有哪些,如何导入外部数据库?

  • 数据 查询(DQL)语言 基本构成 SELECT FROM WHERE
  • 数据 操纵(DML)语言 基本构成 INSERT UPDATE DELETE 
  • 数据 定义(DDL)语言 基本构成 CREATE TABLE VIEW  表的创建 ,属性定义 
  • 数据 控制 (DCL) 语言 主要时对数据库  进行检测  管理(授权,回滚(SQL>ROLLBACK;),提交数据( COMMIT [WORK])) 数据库本质就是文件,android系统下数据库应该存放在/data/data/com..(package name)/目录下,用到的就是文件流FileInputStream完成文件的复制
if(!(newFile(dbfile).exists())) {
  InputStream is =this.context.getResources().openRawResource(R.raw.countries);
  //此处raw下的文件为欲导入的数据库,提前保存在工程目录下
  FileOutputStream fos =newFileOutputStream(dbfile);
  byte[] buffer =newbyte[BUFFER_SIZE];
  int count =0;
  while((count = is.read(buffer)) >0) {
    fos.write(buffer,0, count);
  }
  fos.close();
  is.close();
}

2.是否使用过本地广播,和全局广播有什么差别?

一、本地广播
首先我们要知道,为什么使用本地广播?
本地广播即LocalBroadcastReceiver,仅在自己的应用内发送接收广播,也就是只有自己的应用能收到,数据更加安全广播只在这个程序里,而且效率更高!
引入本地广播的机制主要是为了解决安全性的问题:
1.正在发送的广播不会脱离应用程序,担心app的数据泄露;
2.其他的程序无法发送到自己的应用程序内部,不担心安全漏洞。(比如:如何做一个杀不死的服务---监听火的app 比如微信、友盟、极光的广播,来启动自己。)
3.发送本地广播比发送全局的广播更高效(全局广播要维护的广播集合表效率更低。全局广播,意味着可以跨进程,就需要底层的支持。)
LocalBroadcastReceiver不能静态注册,只能采用动态注册的方式。
LocalBroadcastReceiver使用:
(1)注册
LocalBroadcastManager.getInstance(this).registerReceiver(new XXXBroadCastReceiver(), new IntentFilter(action));
(2) 取消注册:
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
二:全局广播
BroadcastReceiver是针对应用间、应用与系统间、应用内部进行通信的一种方式
BroadcastReceiver可以静态注册,也可采用动态注册的方式。
BroadcastReceiver 使用:
(1)制作intent(可以携带参数)
(2)使用sendBroadcast()传入intent;
(3)制作广播接收器类继承BroadcastReceiver重写onReceive方法
(4)在java中(动态注册)或者直接在Manifest中注册广播接收器(静态注册)使用registerReceiver()传入接收器和intentFilter
(5)取消注册可以在OnDestroy()函数中,unregisterReceiver()传入接收器

3.是否使用过 IntentService,作用是什么, AIDL 解决了什么问题?

Service、IntentService、AIDL简介

4.Activity、 Window、 View 三者的差别, fragment 的特点?

Activity本身是没办法处理显示什么控件(view)的,是通过PhoneWindow进行显示的 换句话说:activity就是在造PhoneWindow,显示的那些view都交给了PhoneWindow处理显示
1、在Activity创建时调用attach方法:
2、attach方法中会调用PolicyManager.makeNewWindow()
实际工作的是IPolicy接口的makeNewWindow方法
①、其中创建了一个window(可以比喻为一个房子上造了一个窗户):mWindow = PolicyManager.makeNewWindow(this);
②、在window这个类中,才调用了setContentView(),这是最终的调用
在Activity的setContentView方法中,实际上是调用:getWindow().setContentView(view, params);这里的getWindow()就是获取到一个Window对象
Tips:
       为啥attch优先于onCreate调用,就是由于在attch方法中,会创建window,有了window才能调用setContentView
3、在IPolicy的实现类中创建了PhoneWindow:
①、由mWindow = PolicyManager.makeNewWindow(this);
②、这里的makeNewWindow(this);方法中,返回的是:return sPolicy.makeNewWindow(context);
③、这个sPolicy实际是一个接口,其实现类是Policy,其中只是创建了一个PhoneWindow
4、在PhoneWindow的setContentView中向ViewGroup(root)中添加了需要显示的内容
①、PhoneWindow是继承Window的
②、setContentView这个方法中,需要先判断一个mContentParent是否为空,因为在默认进来的时候,什么都没创建呢,此时需要创建:installDecor(),DecorView是最根上的显示的 ,可以通过adt中的的tools中有个hierarchyviewer.bat的工具,可以查看手机的结构
③、DecorView:是继承与FrameLayout的,作为parent存在,最初显示的
④、下次再加载的时候,mContentParent就不为空了,会将其中的所有的view移除掉,然后在通过布局填充器加载布局
二、三者关系:
1、在Activity中调用attach,创建了一个Window
2、创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
3、在Activity中调用setContentView(R.layout.xxx)
4、其中实际上是调用的getWindow().setContentView()
5、调用PhoneWindow中的setContentView方法
6、创建ParentView:作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
7、将指定的R.layout.xxx进行填充
通过布局填充器进行填充【其中的parent指的就是DecorView】 8、调用到ViewGroup
9、调用ViewGroup的removeAllView(),先将所有的view移除掉
10、添加新的view:addView()

Fragment可以作为Activity界面的一部分组成出现;
可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
在Activity运行过程中,可以添加、移除或者替换Fragment;
Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响。

5.描述一次网络请求的流程

1.通过URL找IP 首先我们的浏览器是不认识baidu.com这个域名的,...
2.对IP结果建立TCP连接 自己主机IP端口的对目标IP的端口(例:http://www...
3.向服务器发送数据 浏览器将网络请求封装成HTTP报文,把HTTP报文通过TCP的分包...
4.服务器解析,并返回 对HTTP报文进行解析,根据HTTP报文决定它请求了什么。将处理的...
5.浏览器解析HTML 浏览器加载显示html的顺序是:从上到下,渲染的顺序也是从上到下...
查看更多步骤...

6.Handler、 Thread 和 HandlerThread 的差别

①Handler:在android中负责发送和处理消息,通过它可以实现其他支线线程与主线程之间的消息通讯。
②Thread:Java进程中执行运算的最小单位,亦即执行处理机调度的基本单位。某一进程中一路单独运行的程序。
③HandlerThread:一个继承自Thread的类HandlerThread,Android中没有对Java中的Thread进行任何封装,而是提供了一个继承自Thread的类HandlerThread类,这个类对Java的Thread做了很多便利的封装。
原文链接

7.低版本 SDK 实现高版本 api

Android给我们提供了两种注解的方式避免编译时报错:
@SuppressLint
@TargetApi
这两种方法又有什么区别呢?
SupressLint很显然的意思是忽略Lint检查,对于我们使用高版本API来说,可以使用@SuppressLint("NewApi")的方式让Lint在编译时忽略所调用API对版本的要求。而@TargetApi是忽略特定版本的API调用报错。
举个栗子:当你的项目minSdkVersion=9,你想使用API 11的新的方法时。此时,使用@TargetApi(11)和@SuppressLint("NewApi")的效果一样,代码都不会报错。但是如果你使用了Api 19才出现的新的方法时,在使用@TargetApi的方法中还是会给你报错,而在另一个方式中依然不会报错。
那这么讲使用@SuppressLint("NewApi")就更好了?
. 正确的使用姿势
当然不是啦!我们要清楚一点,使用上面两种注释的方式只是让lint在编译时不再报错,在低版本的手机系统中,如果直接使用高版本的API肯定会报:“NoSuchMethod”的Crash的。 所以正确的做法应该是在注解的方法中,做版本判断,在低版本中依然使用老的方式处理。版本判断时我们需要判断具体的版本号,比如

 1@TargetApi(9)
 2public void doSomeThing() {
 3    if(Build.VERSION.SDK_INT >= 9) {
 4        // 此时我们正常使用API 9的方法,如果这里误使用了Api 11中的方法,编译时就会报错
 5        // 提醒我们只是引入API 9中的方法
 6    } else {
 7        // TODO 使用老的方式
 8    }
 9}
10
11@SuppressLint("NewApi")
12public void doOthers() {
13    if(Build.VERSION.SDK_INT >= 9) {
14        // 此时我们正常使用API 9的方法,如果这里误使用了Api 11中的方法,编译不会报错
15        // 那么运行在低版本中将会引发Crash的风险
16    } else {
17        // TODO 使用老的方式
18    }
19}

8.launch mode 应用场景

android launchMode理解以及应用场景

9.touch 事件传递流程

10.view 绘制流程

11.什么情况导致内存泄漏

12.ANR 定位和修正

13.什么情况导致 oom

14.Android Service 与 Activity 之间通信的几种方式

15.Android 各个版本 API 的区别

16.如何保证一个后台服务不被杀死,比较省电的方式是什么?

17.Requestlayout, onlayout, onDraw, DrawChild 区别与联系

18.invalidate()和 postInvalidate() 的区别及使用

19.Android 动画框架实现原理

20.Android 为每个应用程序分配的内存大小是多少?

21.LinearLayout 对比 RelativeLayout

22.优化自定义 view

23.ContentProvider

24.fragment 生命周期

25.volley 解析

26.Android Glide 源码解析

27.Android 属性动画特性