Android 基础与底层机制面试题,万字解析
标准模式
SingleTop:使用场景:浏览器的书签;通讯消息聊天界面。
SingleTask:使用场景:某个 Activity 当做主界面的时候。
SingleInstance:使用场景:比如浏览器 BrowserActivity 很耗内存,很多 app 都会要调用 它,这样就可以把该 Activity 设置成单例模式。比如:闹钟闹铃。
7. view 绘制流程(百度)
Measure:测量,测量自己。如果是 ViewGroup 就需要测量里面的所有 childview.
测 量 的 结 果 怎 么 办 ? setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), heightSizeAndState);设置自己的大小。
Layout: 摆放,把自己摆放在哪个位置。如果是 ViewGroup 就需要发放里面的所有 childview.
怎么去具体摆放呢?
Draw:绘制
/*
Draw traversal performs several drawing steps which must be executed
in the appropriate order:
Draw the background
If necessary, save the canvas' layers to prepare for fading
Draw view's content
Draw children
If necessary, draw the fading edges and restore layers
Draw decorations (scrollbars for instance) */
8. 什么情况导致内存泄漏(美团)
1)什么是内存泄漏:最好解释清楚 GC 垃圾回收机制以及概念 GC Root。
2)为什么会有内存泄漏:因为内存泄漏是属于人为的失误造成的。而且面向对象开发 关系复杂、多线程的关系,很容易出现引用层级关系很深以及很混乱。
3)什么情况容易导致内存泄漏;
4)如何解决内存泄漏;
9. ANR 定位和修正
可以通过查看/data/anr/traces.txt 查看 ANR 信息。
根本原因是:主线程被卡了,导致应用在 5 秒时间未响应用户的输入事件。
很多种 ANR 错误出现的场景:
1) 主线程当中执行 IO/网络操作,容易阻塞。
2) 主线程当中执行了耗时的计算。----自定义控件的时候 onDraw 方法里面经常这么 做。(同时聊一聊自定义控件的性能优化:在 onDraw 里面创建对象容易导致内存抖动 —绘制动作会大量不断调用,产生大量垃圾对象导致 GC 很频繁就造成了内存抖动。)内存抖动就容易造成 UI 出现掉帧卡顿的问题。
3) BroadCastReceiver 没有在 10 秒内完成处理。
4) BroadCastReceiver 的 onReceived 代码中也要尽量减少耗时的操作,建议使用 IntentService 处理。
5) Service 执行了耗时的操作,因为 service 也是在主线程当中执行的,所以耗时操 作应该在 service 里面开启子线程来做。
6) 使用 AsyncTask 处理耗时的 IO 等操作。
7) 使 用 Thread 或 者 HandlerThread 时 , 使用 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) 或 者 java.lang.Thread.setPriority (int priority)设置优先级为后台优先级,这 样可以让其他的多线程并发消耗 CPU 的时间会减少,有利于主线程的处理。
8) Activity 的 onCreate 和 onResume 回调中尽量耗时的操作。
10. 什么情况导致 oom(乐视、美团)
OOM 产生的原因:内存不足,android 系统为每一个应用程序都设置了一个硬性的条件: DalvikHeapSize 最大阀值 64M/48M/24M.如果你的应用程序内存占
用接近这个阀值,此时如 果再尝试内存分配的时候就会造成 OOM。
1)内存泄露多了就容易导致 OOM
2)大图的处理。压缩图片。平时开发就要注意对象的频繁创建和回收。
3)可以适当的检测:ActivityManager.getMemoryClass()可以用来查询当前应用的 HeapSize 阀值。可以通过命名 adb shellgetProp | grep dalvik.vm.heapxxxlimit 查看。
如何避免内存泄露:
1) 减小对象的内存占用:
a) 使用更加轻量级的数据结构: 考虑适当的情况下替代 HashMap 等传统数据结构而使用安卓专门为手机研发 的 数 据 结 构 类 ArrayMap/SparseArray 。 SparseLongMap/SparseIntMap/SparseBoolMap 更加高效。 HashMap.put(string,Object);Object o = map.get(string);会导致一些没必 要的自动装箱和拆箱。
b) 适当的避免在 android 中使用 Enum 枚举,替代使用普通的 static 常量。(一 般还是提倡多用枚举—软件的架构设计方面;如果碰到这个枚举需要大量使 用的时候就应该更加倾向于解决性能问题。)。
c) 较少 Bitmap 对象的内存占用。 使用 inSampleSize:计算图片压缩比例进行图片压缩,可以避免大图加载造成 OOM; decodeformat : 图 片 的 解 码 格 式 选 择 , ARGB_8888/RGB_565/ARGB_4444/ALPHA_8,还可以使用 WebP。
d) 使用更小的图片 资源图片里面,是否存在还可以继续压缩的空间。
2) 内存对象的重复利用: 使用对象池技术,两种:
1.自己写;
2.利用系统既有的对象池机制。比如 LRU(Last Recently Use)算法。
a) ListView/GridView 源 码 可 以 看 到 重 用 的 情 况 ConvertView 的 复 用 。RecyclerView 中 Recycler 源码。
b) Bitmap 的复用 Listview 等要显示大量图片。需要使用 LRU 缓存机制来复用图片。
c) 避免在 onDraw 方法里面执行对象的创建,要复用。避免内存抖动。
d) 常见的 java 基础问题—StringBuilder 等
3) 避免对象的内存泄露;
4) 使用一些内存的优化策略: 看文档
11. Android Service 与 Activity 之间通信的几种方式
1)通过 Binder
2)通过广播
12. Android 各个版本 API 的区别
把几个关键版本的特性记住:3.0/4.0、4.4、5.0、6.0/7.0……
13. Requestlayout, onlayout, onDraw, DrawChild 区别与 联系(猎豹)
RequestLayout()方法:会导致调用 Measure()方法和 layout()。将会根据标志位判断是否 需要 onDraw();
onLayout():摆放 viewGroup 里面的子控件
onDraw():绘制视图本身;(ViewGroup 还需要绘制里面的所有子控件)
drawChild(): 重 新 回 调 每 一 个 子 视 图 的 draw 方 法 。 child.draw(canvas, this, drawingTime);
14. invalidate()和 postInvalidate() 的区别及使用(百度)
invalidate():在主线程当中刷新;
postInvalidate():在子线程当中刷新;其实最终调用的就是 invalidate,原理依然 是通过工作线程向主线程发送消息这一机制。
public void postInvalidate() {
postInvalidateDelayed(0);
}
public void postInvalidateDelayed(long delayMilliseconds) {
// We try only with the AttachInfo because there's no point in invalidating
// if we are not attached to our window
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
}
}
public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
mHandler.sendMessageDelayed(msg, delayMilliseconds);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INVALIDATE: ((View) msg.obj).invalidate();
}
break;
15. Android 动画框架实现原理(腾讯)
传统的动画框架:View.startAnimation();
弊端:移动后不能点击。原因?跟实现机制有关系。
所有的透明度、旋转、平移、缩放动画,都是在 view 不断刷新调用 draw 的情况下实现的。
调用的 canvas.translate(xxx),canvas.scaleX(xxx)…. Xxx:matrix 像素矩阵来控制动画 的数据。记得看源码,结合多只缩放的 demo 看源码。
16. Android 为每个应用程序分配的内存大小是多少?(美团)
看具体的手机平台,常见的有:64M/32M 等。
17. LinearLayout 对比 RelativeLayout(百度)
性能对比:LinearLayout 的性能要比 RelativeLayout 好。
因为 RelativeLayout 会测量两次。而默认情况下(没有设置 weight)LinearLayout 只会测 量一次。
为什么 RelativeLayout 会测量两次?首先 RelativeLayout 中的子 view 排列方式是基于彼 此依赖的关系,而这个依赖可能和布局中 view 的顺序无关,在确定每一个子 view 的位置的 时候,就需要先给每一个子 view 排一下序。又因为 RelativeLayout 允许横向和纵向相互依 赖,所以需要横向纵向分别进行一次排序测量。
18. 优化自定义 view(百度、乐视、小米)
1)减少在 onDraw 里面大量计算和对象创建和大量内存分配。
2)应该尽量少用 invalidate()次数。
3)view 里面耗时的操作 layout。减少 requestLayout()避免让 UI 系统重新遍历整 棵树。Mearsure。
4)如果你有一个很复杂的布局,不如将这个复杂的布局直接使用你自己的写的 ViewGroup 来实现。减少了一个树的层次关系 全部都是自己测量和 layout,达到优化 的目的。(Facebook 就经常这么干)
19. ContentProvider(乐视)
提示:跨进程通信。进程之间进行数据交互共享。
评论