当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。
Message Queue
Android在第一次启动程序时会默认会为UI thread创建一个关联的消息队列,可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。
每个Handler都会与唯一的一个线程以及该线程的消息队列关联。
Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。
Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。Handler里会引用当前线程里的特定Looper和MessageQueue。
在Handler.java的sendMessageAtTime(Message msg, long uptimeMillis)方法中,我们看到,它找到它所引用的MessageQueue,然后将Message的target设定成自己(目的是为了在处理消息环节,Message能找到正确的Handler),再将这个Message纳入到消息队列中。
Looper.java的loop()函数里,我们看到,这里有一个死循环,不断地从MessageQueue中获取下一个(next方法)Message,然后通过Message中携带的target信息,交由正确的Handler处理(dispatchMessage方法)。
Handler.java的dispatchMessage(Messagemsg)方法里,其中的一个分支就是调用handleMessage方法来处理这条Message,而这也正是我们在职责处描述使用Handler时需要实现handleMessage(Message msg)的原因。
主线程(UI线程)里,如果创建Handler时不传入Looper对象,那么将直接使用主线程(UI线程)的Looper对象(系统已经帮我们创建了);在其它线程里,如果创建Handler时不传入Looper对象,那么,这个Handler将不能接收处理消息。在这种情况下,通用的作法是:
· Handler的处理过程运行在创建Handler的线程里
· 一个Looper对应一个MessageQueue,一个线程对应一个Looper
· 一个Looper可以对应多个Handler
· 不确定当前线程时,更新UI时尽量调用post方法
Handler类用于处理消息. 该类具有四个构造函数:
1. public Handler(). 创建好的Handler instance将绑定在代码所在的线程的消息队列上, 因此一定要确定该线程开启了消息队列, 否则程序将发生错误. 使用这个构造函数创建Handler instance, 一般来说, 我们需要重写Hanler类的handleMessage()方法, 以便在之后的消息处理时调用.
2. public Handler(Callback callback). Callback是Handler内部定义的一个接口, 因此想要使用这个构造函数创建Handler对象, 需要自定义一个类实现Callback接口, 并重写接口中定义的handleMessage()方法. 这个构造函数其实与无参的构造函数类似, 也要确保代码所在的线程开启了消息队列. 不同的是在之后处理消息时, 将调用callback的handleMessage()方法, 而不是Handler对象的handleMssage()方法.
3. public Handler(Looper looper). 这个构造函数表示创建一个Handler instance, 并将其绑定在looper所在的线程上. 此时looper不能为null. 此时一般也需要重写Hanler类的handleMessage()方法
4. public Handler(Looper looper, Callback callback). 可以结合2和3理解.
从消息队列中取出消息并处理消息: 所有在消息队列中的消息, 都具有target字段. 消息是在target所关联的线程上被取出和处理的.
1. 如果取出的Message对象的callback字段不为null, 那么就调用callback字段的run()方法(callback字段的类型是runnable). 注意此时并不开启一个新的线程运行run()方法, 而是直接在handler对象(即Message的target字段)所关联的线程上运行.
2. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段也为null, 那么这个消息将由Handler对象的handleMessage(msg)方法处理. 注意Message对象的callback字段是Runnable类型的而Handler对象的callback字段是Callback类型的, Handler对象的callback字段是在创建Handler instance的时候指定的, 如果没有指定则这个字段为null, 详见Handler类的四个构造方法.
3. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段不为null, 那么这个消息将由Handler对象中的callback字段的handleMessage方法处理.
looper类
prepare()方法:
为static方法。首先判断当前线程是否已经建立了looper(),若否则创建。looper就是当前线程的消息泵的意思。每个线程只有一个。
loop()方法
为static方法。首先获取当前线程的looper对象。接下来不断的给队列里每一个message的target发送。
handler类
myLooper方法:
获取线程的Looper,没有则创建。同时保证了messagequeue的有效性(message queue和looper是同时有效的)。
handler()方法:
无参数的构造函数,若在当前线程里运行则获得当前线程的looper和message queue。
dispatchmessage方法
有looper调用。对消息的处理过程是首先是message的callback方法。接下来是handler类的callback方法,最后是handler的handlemessage方法
looper和handler类的意义
looper是线程的消息泵,messagequeue是承载体。handler是消息的消费者。也能够发送消息。looper和线程对象一一对应。handler通过与线程一一对应的looper处理某个线程的消息。而handler的无参数构造函数是为了能够方便的处理正在执行这个无参数构造函数的线程的消息队列而设计的方法,能够自动获取当前线程的looper对象。