我理解的Handler,messageQueue,Looper,Messager,HandlerThread.

来源:互联网 发布:数据脱敏的主要方法 编辑:程序博客网 时间:2024/06/05 10:56

网上深入讲这些知识的很多,我就写一些总结性与结论性的东西吧。

1.一个app在开启时会给我们创建Looper,MessageQueue是Looper的成员变量,在Lp的构造中被new MessageQueue(),一个线程对应一个Looper,一个Looper对应一个MessageQueue.

2.Handler的构造方法中会获取其所在线程的Looper与MessageQueue,通过成员变量来保存,有则绑定,无则报错。在用handler发送消息后,Message内部会通过变量target保存handler(把自己发送出去的),方便后续回调,同时,把Messager放入到了MessageQueue中,实现轮循消息队列中的消息。

3.Looper调用loop()方法,该方法是一个死循环,即安卓系统只要不崩溃,该方法就会一直执行,至于为什么不会ANR,网上说这是网易的一个面试题,网友没有给出原理,据说是因为:该looper,处理安卓所有的主线程的消息,当然包括系统消息,如果ANR了,则系统便无法继续运行下去,因此是一个无限循环是没问题的,至于,如何强制退出,下面会讲到。接着讲loop(),该方法中,每次从MessagerQueue中拿到消息,就会调用msg.target.dispatchMessage(msg);即发送消息的handler的方法。在该方法中,有一个判断,如果消息是一个callback对象则走对象的run(),否则走handler的handlerMessager(),这也是为何可以用持有主线程Looper的handler来实现直接更新UI操作的原因了。

4上面讲到退出looper()方法,两种方法,Looper.quit(),Looper.quitSafely(),前者直接清空MessageQueue里的所有消息,使Looper无法工作,后者只是清空一些延迟执行的Message,让handler可以执行完重要的Message后停止执行。

5.在主线程中更新UI还是在子线程中更新UI,重点在Looper,只要handler持有的Looper是主线程的,即Handler handler = new Handler(Looper.getMainLooper());则该handler在哪里都可以更新UI的,实现在子线程中更新UI。

6.通过Handler加HandlerThread来实现处理耗时操作,HandlerThread就是一个初始化了looper的子线程,可以通过它把looper以构造的形式传递给handler,从而主线程的handler也将可以处理耗时操作了。

7.在HandelerThread的内部,getLooper()方法里有wait()方法,而其构造方法中有notifyAll()方法,是为了实现线程传参的同步。即UI线程中的Handler会执行的更快一些,所以在它构造里的值用一个可以等待的方法来传值,当等到HandlerThread的run()方法执行完毕了,即Looper初始化完毕了,再唤醒getLooper(),从而成功 把子线程中的looper传递给了handler对象。

阅读全文
0 0