Android 弃暗投明之Handler

来源:互联网 发布:成功瘦下来 知乎 编辑:程序博客网 时间:2024/06/17 03:12
弃暗投明在这里是个戏称,我想表达的是拨开乌云重见天日的意思。

一、引言
操作系统中资源分配和调度的基本单元是进程,Android操作系统也不例外。进程还可以细化成线程,线程由CPU调度和分配的基本单位。Android的每个应用程序都由zygote fork出来并分配的自己的uid和gid进行沙盒隔离,而进程内的线程间是否可以直接通信呢?根据Android的JMM(内存模型)我们知道,同一进程内的线程都有自己的LTS(本地存储),他们通过主内存同步变量。
那么如果一个线程想发消息给另一个线程,该如何做呢?

二、Handler官方描述
最新的Android7.1.1_r6对Handler是这样描述的
/**25 * A Handler allows you to send and process {@link Message} and Runnable26 * objects associated with a thread's {@link MessageQueue}. Each Handler27 * instance is associated with a single thread and that thread's message28 * queue. When you create a new Handler, it is bound to the thread /29 * message queue of the thread that is creating it -- from that point on,30 * it will deliver messages and runnables to that message queue and execute31 * them as they come out of the message queue.32 *
Handler允许你发送处理“Message”和“Runnable”,每个Handler实例关联一个线程及其消息队列。当你创建Handler时,它就关联了创建它的线程的消息队列。此后,它就会将Message和Runnable发送给消息队列并在出队时处理它们。
33 * <p>There are two main uses for a Handler: (1) to schedule messages and34 * runnables to be executed as some point in the future; and (2) to enqueue35 * an action to be performed on a different thread than your own.36 *
Handler有两大用途:
(1)计划message或runnables在指定时间点执行
(2)让一个任务在另一个线程执行
37 * <p>Scheduling messages is accomplished with the38 * {@link #post}, {@link #postAtTime(Runnable, long)},39 * {@link #postDelayed}, {@link #sendEmptyMessage},40 * {@link #sendMessage}, {@link #sendMessageAtTime}, and41 * {@link #sendMessageDelayed} methods. The <em>post</em> versions allow42 * you to enqueue Runnable objects to be called by the message queue when43 * they are received; the <em>sendMessage</em> versions allow you to enqueue44 * a {@link Message} object containing a bundle of data that will be45 * processed by the Handler's {@link #handleMessage} method (requiring that46 * you implement a subclass of Handler).47 *
计划message执行用post/postAtTime/postDelayed/sendEmptyMessage/sendMessage/sendMessageAtTime/sendMessageDelayed方法完成,post系列方法可以放入消息队列一个Runnable对象,send系列方法则放入消息队列一个包含数据的Message对象,
48 * <p>When posting or sending to a Handler, you can either49 * allow the item to be processed as soon as the message queue is ready50 * to do so, or specify a delay before it gets processed or absolute time for51 * it to be processed. The latter two allow you to implement timeouts,52 * ticks, and other timing-based behavior.53 *54 * <p>When a55 * process is created for your application, its main thread is dedicated to56 * running a message queue that takes care of managing the top-level57 * application objects (activities, broadcast receivers, etc) and any windows58 * they create. You can create your own threads, and communicate back with59 * the main application thread through a Handler. This is done by calling60 * the same <em>post</em> or <em>sendMessage</em> methods as before, but from61 * your new thread. The given Runnable or Message will then be scheduled62 * in the Handler's message queue and processed when appropriate.63 */

三、Handler源码分析

Handler并不是单独作战的,和其相关的有还有两个非常重要的类,就是Looper和MessageQueue。
1. MessageQueue
Handler发送的消息,可以立即处理也可以延时处理,肯定需要一个容器来存放消息。MessageQueue就是这样一个消息队列。
2. Looper
Message被Handler发送出来,会被放入MessageQueue中,放入其中的Message在条件成熟的时候会被取出来,交由Handler去处理。整个过程中还需要一个对象来执行获取并放入,取出并交给对应Handler的工作。这个工作就由Looper来完成。
Looper需要执行两个过程:(1)与线程进行绑定prepare方法(2)读取消息队列中的消息并交由Handler进行处理loop方法

一个线程对应一个Looper、一个MessageQueue以及多个Handler、多个Message
一个Message对象,在被发送的时候将发送该Message对象的Handler对象的引用保存到target成员变量上,looper在轮询Message的时候,就直接把该Message交给message.target这个Handler去处理就可以了。
在调用Handler的sendMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过 ThreadLocal.set(new Looper())跟一个Thread绑定了。Looper对象所属的线程在Looper.Loop方法中循环执行如下步骤:从MessageQueue队列读取 Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

两种方式:
handler发送消息的方法是比较多,常用的就包括
获取消息包括Runnable对象和message对象两种,获取Message的方式包括:
1 直接new一个Message,设置what等参数(不推荐)。
2 通过handler获取复用的Message(推荐)

post方式:发送runnable,实际上是把runnable对象设置为一个Message的成员变量callback之后,发送该Message。最后都是走到sendMessageDelayed方法当中。唯一的区别在于,post方式的Message的callback不是null,send方式发送的Message的callback是null。



原创粉丝点击