知识体系六:Android 主线程到底是什么
1.android 主线程是在哪里创建的?
android的主线程是在 app 进程创建时候就创建了,即当系统 调用 fork()方法之后就会创建一个新的进程和进程中地一个线程称为主线程。
2.android ActivityThread 中创建的 Handler没有指定当前的looper对象那他是怎么保证能通知到主线程的?对应的 HandlerThread 中创建的Handler 却指定了一个looper?
因为ActivityThread中先调用了Looper.prepare()这时候会为当前线程创建Looper和MessageQueue对象,再创建的Handler时候当前Handler就会去调用当前的Looper和MessageQueue对象。
HandlerThread 在当前线程中也是先调用了Looper.prepare(),但是Handler的创建是交给调用者调用方法触发的,这个方法可以在任何线程中调用,所以这时候在创建Handler对象时候就需要指定 传入 looper对象。也可以调整一下Handler的创建位置,放到run()方法内调用就不用传looper了,但是run()中创建对象不是好的编程方式。
3.在android开发中为什么子线程不能更新UI界面?
其实更新UI界面并不是非的在main线程中,子线程不能更新ui界面的原因是因为当我们进程fork()并启动时创建的地一个线程就是main线程,然后就调用了ActivityThread 中的 main()方法开始loop循环处理handler接受到的消息。application 创建完之后会等待 AMS 回调ApplicationThread 跨进程接口,当收到Launcher activity信号后application就会创建activity然后一直到ViewRootImpl中通知WMS创建窗口并且更新绘制各个子View控件,在ViewRootImpl的构造方法内已经保存了当前创建的 thread 对象,由于ViewRootImpl创建是在main线程中的,所以thread这个对象其实就是main线程。当我们再次调用更新View的方法时例如invalidate()/ requestLayout()等触发更新界面时都会调用checkThread()方法去验证当前的 thread 是不是ViewRootImpl构造方法中保存的那个线程,不是就会抛出异常。android 加检测线程的原因其实是为了防止多线程访问下触发线程安全问题,但是为了降低锁带来的开销和系统的复杂度,就强制限制必须是我们创建 ViewRootImpl 对象的线程。所以如果我们想在子线程中更新UI 其实两种方式 1.我们创建ViewRootImpl时在子线程中创建。2.反射修改checkThread()方法的结果。
4.android 主线程是如何捕获ANR异常的?
1.Service Timeout:服务在20s内未执行完成;
2.BroadcastQueue Timeout:比如前台广播在10s内执行完成
3.ContentProvider Timeout:内容提供者执行超时
4.inputDispatching Timeout: 输入事件分发超时5s,包括按键分发事件的超时。