### Android面试集锦--基础部分
#### 1.请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系
那主线程来说,首先启动时会调用Looper.prepare(),会初始化一个Looper,放在Threadlocal中,接下来会调用Looper.looper()进行遍历Message Queue,Handler的创建依赖于当前线程中的Looper,如果当前线程没有Looper则必须调用Looper.prepare(),Handler , sendMessage到MessageQueue,Looper不断从MessageQueue中取出消息,回调handleMessage方法。
#### 2.生命周期
![](https://box.kancloud.cn/060c7e1ff5e36a7ba764388d5edcf05e_554x556.jpg)
![](https://box.kancloud.cn/e6602bd3e93a32353be0335dc08978dc_702x718.jpg)
![](https://box.kancloud.cn/f4088dc5159b4d0bd4292983e1f63753_565x733.jpg)
#### 3.内存溢出与内存泄露的区别,内存优化的方法有哪些?
内存溢出是指应用程序所需要的内存超出系统分配的最大内存导致的OOM
内存泄露是我们对某一内存空间,在使用完成后未进行释放即长生命周期的对象持有短生命周期的对象,短周期对象就无法及时释放
内存优化:内存溢出主要发生在图片的处理上,图片的加载,我们可以使用图片的压缩加上使用LruCache缓存的目的来控制图片所能够使用的内存、避免在android里面使用Enum、减少bitmap的内存占用。
如何避免 OOM 异常
1.减少内存对象的占用
* ArrayMap/SparseArray代替hashmap
* 避免在android里面使用Enum
* 减少bitmap的内存占用
* inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
* decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异
* 减少资源图片的大小,过大的图片可以考虑分段加载
2.对象的重复利用
* listview/gridview/recycleview contentview的复用
* inBitmap 属性对于内存对象的复用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8这个方法在某些条件下非常有用,比如要加载上千张图片的时候
* 避免在ondraw方法里面 new对象
* StringBuilder 代替+
#### 4.ANR 是什么?怎样避免和解决 ANR
ANR=Application Not Responding即规定时间内未做出响应
三种类型:
* KeyDispatchTimeout(5 s) --主要类型按键或触摸事件在特定时间内无响应
* BroadcastTimeout(10 s) --BroadcastReceiver在特定时间内无法处理完成
* ServiceTimeout(20 s) --小概率类型 Service在特定的时间内无法处理完成
为什么会超时?事件没有机会处理或者事件处理超时
怎么避免ANR
ANR的关键是处理超时,所以应该避免在UI线程,BroadcastReceiver 还有service主线程中,处理复杂的逻辑和计算而交给work thread(子线程)操作。
* 避免在activity里面做耗时操作,oncreate & onresume
* 避免在onReceiver里面做过多操作
* 避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
* 尽量使用handler来处理UI thread & workthread的交互
#### 5.Android 线程间通信有哪几种方式
1. 共享变量(内存)
2. 管道
3. handle机制
* runOnUiThread(Runnable)
* view.post(Runnable)/new Handler().postDelayed(Runnable)
#### 6.描述一下 android 的系统架构
从小到上就是:
linux kernel,lib dalvik vm ,application framework, app
#### 7.Android四大组件介绍
1. Activity
* 用户进行交互的可视化操作组件,可以简单理解成一个Activity就一个窗口。
* Activity之间通过Intent来进行通信。
* Android的应用在创建一个Activity的时候都需要在AndroidManifest.xml配置文件中配置。
2. BroadCaseReceiver
* 广播接收者是没有用户界面,它们可以启动一个Activity或Service来响应它们收到的信息,或者用NotificationManager来通知用户。
* 广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest.xml配置文件进行静态注册。
* 动态注册广播接收器的特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关掉,只要设备是开启装逼,广播接收器也是开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
3. Service
* Service用于在Android手机后台完成用户的操作,Service分为两种:
(a)started(启动):当应用程序组件(如Activity)调用startService()方法启动服务时,服务处于started状态。
(b)bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。
* startService()与bindService()的区别:
(a)启动服务是由其他组件调用startService()方法启动的,这样服务的onStartService()方法被调用,当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
(b)使用bindService()方法启动服务,调用者与服务绑定在了一起,Service与调用组件的生命周期协同。
* 使用Service时候同样需要我们在AndroidManifest.xml声明使用的service,使用的是标签。
* Service通常是后台运行的,不太需要进行用户交互的动作,所以被称之为没有图形用户界面。Service组件被某些动作触发然后在后台为我们服务或者监控我们的交互操作。
4. Content Provider
* android平台提供了Content Provider使一个应用程序的指定数据给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。
* 只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
* ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不用应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。
* 开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。
* ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。
#### 8.启动模式
Android有四种启动模式,分别是
1.standard (默认模式)
每次启动一个Activity都会重写创建一个新的实例
2.singleTop(栈顶复用模式)
当启动Activity时如果已经存在于栈顶则不会重新创建新的实例,如果不在栈顶则跟默认模式没区别即还会创建新的实例
3.singleTask(栈内复用模式)
官方称:当处于singleTask模式时最多仅有一个实例存在,并且位于一它为根的task,所有对该Activity的请求,都会跳到该Activity的Task中展开进行。如果我们使用时,该Activity不在栈顶,那么位于它上方的Activity就会全部出栈,从而使其回到栈顶。什么时候使用该模式呢?我们一般在创建开销较大且经常被其他APP调用的Activity中使用,这种Activity一般作为程序的入口,比如浏览器的主页使用的就是singleTask
4.singleInstance(全局唯一模式)
singleInstance模式和singleTask很相似,他们的不同点仅在于,该模式下的Activity是它所属任务栈中的唯一Activity。可以看出,这样的Activity封闭性极强,能够很好地保持唯一性,也能大大减少不必要的开销。一个应用的例子就是XX地图,如果APP中使用了XX地图,那么当我们切到桌面,并进入到XX地图时,看到的页面跟之前是一样的。
#### 9.请介绍下Android的数据存储方式
1.SharedPreferences
2.Content Provider
3.文件储存方式
4.网络储存数据
5.数据库存储数据
#### 10. 退出Activity有哪几种方式
1.建立一个全局容器将所有的Activity放在容器堆栈内,退出的时候进行遍历退出
2.用广播
3.杀进程
4.广播+singleTask
#### 11.Activity、Window、View三者的差别,fragment的特点?
1.Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutInflater像剪刀,Xml配置像窗花图纸。
2.在Activity中调用attach,创建了一个Window
1. 创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
2. 在Activity中调用setContentView(R.layout.xxx)
3. 其中实际上是调用的getWindow().setContentView()
4. 调用PhoneWindow中的setContentView方法
5. 创建ParentView:作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
6. 将指定的R.layout.xxx进行填充通过布局填充器进行填充【其中的parent指的就是DecorView】
7. 调用到ViewGroup
8. 调用ViewGroup的removeAllView(),先将所有的view移除掉
9. 添加新的view:addView()
fragment 特点
1. Fragment可以作为Activity界面的一部分组成出现;
2. 可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
3. 在Activity运行过程中,可以添加、移除或者替换Fragment;
4. Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主5. Activity的生命周期影响。
![](https://box.kancloud.cn/2016-03-01_56d551f0cd6a3.jpg)
Fragment生命周期