Android 常见面试问题整理
对 Android 面试常见问题点进行总结分析,方便对碎片知识进行回顾。
Android 基础常见面试问题的整理,会持续更新…
Handler
说下 handler 机制,Looper 通过 MessageQueue 取消息,消息队列是先进先出模式,那我延迟发两个消息,第一个消息延迟 2 个小时,第二个消息延迟 1 个小时,那么第二个消息需要等 3 个小时才能取到吗?
MessageQueue 的实现不是队列,不要被名称迷惑,他是一个链表;每次发送消息都会按照 delay 值从小到大进行重排;所有的 delay 消息都是并行的,不是串行的;第一个延迟 2 个小时,第二个延迟 1 小时,会优先执行第二个,再过 1 小时执行第一个。
Android 为什么不能在子线程更新 UI ?
谷歌提出:“一定要在主线程更新UI”,实际是为了提高界面的效率和安全性,带来更好的流畅性;
反推一下,假如允许多线程更新UI,但是访问 UI 是没有加锁的,一旦多线程抢占了资源,那么界面将会乱套更新了,体验效果就不言而喻了;
UI 控件是非线程安全,在多线程中并发访问可能会导致UI控件处于不可预期的状态。所以在Android中规定必须在主线程更新UI。
不对 UI 控件的访问加上锁机制的原因?
上锁会让UI控件变得复杂和低效;
上锁后会阻塞某些进程的执行;
在 Activity 的 onCreate 里开一个子线程更新 UI,可以运行吗?
1 | public class MainActivity extends Activity { |
事件结果是可以运行。
原因如下
1 | public final class ViewRootImpl implements ViewParent, |
ViewRootImpl
对象是在 onResume 方法回调之后才创建,那么就说明了为什么在生命周期的 onCreate() 方法里,甚至是 onResume() 方法里都可以实现子线程更新 UI,因为此时还没有创建 ViewRootImpl 对象,并不会进行是否为主线程的判断, 也就是 ViewRootImpl 的 checkThread() 会检查,而 ViewRootImpl 是在 onResume() 方法里创建。onCreate() 里还没有创建 ViewRootImpl,所以不会抛出异常。
如果耗时的话,才会抛出异常,可以尝试让线程休眠 100ms or 1000ms。