Android 中handler 机制 概括起来需要三个步骤。
我们要从零开始实现handler 的机制,先从handler 要实现的功能开始。
Handler.java
package com.android;
public class Handler {
final Looper mLooper;
final MessageQueue mQueue;
public Handler( ) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
}
public boolean sendMessage(Message msg ) {
System.out.println("sendMessage");
synchronized(mQueue) {
msg.target = this;
mQueue.add(msg);
System.out.println("唤醒");
mQueue.notifyAll();
}
return true;
}
public void handleMessage(Message msg) {
}
public void dispatchMessage(Message msg) {
System.out.println("dispatchMessage");
handleMessage(msg);
}
}
Handler 需要实现 sendMessage 和 dispatchMessage , 即发送消息到 消息队列 和从消息队列取消息并处理, 典型的生产者和消费者模型。 只是这个消息队列属于当前线程。当前线程的消息队列 用mLooper.mqueue 来表示。 那么问题来了。 如果来实现当前线程的消息队列。
Looper.java
package com.android;
import java.lang.ThreadLocal;
public final class Looper {
private static final String TAG = "Looper";
static final ThreadLocal sThreadLocal = new ThreadLocal();
final MessageQueue mQueue;
private static Looper sMainLooper; // guarded by Looper.class
private Looper(boolean quitAllowed) {
System.out.println("Looper 构造函数");
mQueue = new MessageQueue( );
}
public static Looper myLooper() {
System.out.println("myLooper");
return sThreadLocal.get();
}
public static void prepareMainLooper() {
System.out.println("prepareMainLooper");
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
System.out.println("prepare");
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static void loop() {
System.out.println("loop");
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
for (;;) {
synchronized(queue) {
while (queue.size() == 0) {
try {
System.out.println("wait here" );
queue.wait();
} catch (Exception e) {
System.out.println("wait error" + e.toString());
}
}
if (queue.size() > 0) {
System.out.println("处理消息"+ queue.size());
Message msg = queue.poll();
msg.target.dispatchMessage(msg);
System.out.println("处理完毕");
}
}
}
}
}
这里的Looper.prepare 就是将Looper和当前线程绑定。
Looper 是一个不断循环 从消息队列读消息并处理的生产者消费者模型。不断循环即由loop的for 循环驱动。 在消息队列没有消息时, 线程处于等待状态。当有消息入队时,通知线程处理 dispatchMessage。
Android 源码中的MessageQueue 实现方式 比较繁琐, 这里可以为了方便叙述和理解,直接使用java 的queue 。
MessageQueue.java
package com.android;
import java.util.*;
public class MessageQueue implements Queue {
Queue queue;
MessageQueue(){
System.out.println("MessageQueue 构造函数");
queue = new LinkedList();
}
@Override
public int size() {
return queue.size();
}
@Override
public boolean isEmpty() {
if( queue.size()==0){
return true;
}else{
return false;
}
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public Object[] toArray(Object[] objects) {
return new Object[0];
}
@Override
public boolean add(Object o) {
System.out.println("add ");
if( Message.class.isInstance(o)){
queue.add((Message) o);
System.out.println("current size "+queue.size());
return true;
}else{
return false;
}
}
@Override
public boolean remove(Object o) {
if( Message.class.isInstance(o)){
queue.remove(o);
}else{
return false;
}
return true;
}
@Override
public boolean addAll(Collection collection) {
return false;
}
@Override
public void clear() {
queue.clear();
}
@Override
public boolean retainAll(Collection collection) {
return false;
}
@Override
public boolean removeAll(Collection collection) {
return false;
}
@Override
public boolean containsAll(Collection collection) {
return false;
}
@Override
public boolean offer(Object o) {
System.out.println("off ");
if( Message.class.isInstance(o)){
queue.offer((Message) o);
}else{
return false;
}
return true;
}
@Override
public Message remove() {
Message msg = queue.remove();
return msg;
}
@Override
public Message poll() {
System.out.println("poll ");
Message msg = queue.poll();
return msg;
}
@Override
public Message element() {
Message msg = queue.element();
return msg;
}
@Override
public Message peek() {
System.out.println("peek ");
Message msg = queue.peek();
return msg;
}
}
这里我们的MessageQueue 使用queue 接口类。
Message类这里只包含 target 和what 成员。
Message.java
package com.android;
public final class Message {
public int what;
Handler target;
}
Handler 成员此时已经集齐,是时候放到一个线程里让其运转起来了。 这里我们分析ActivityThread的源码,并提取 handler 相关的部分。
package com.android;
public final class ActivityThread {
static volatile Handler sMainThreadHandler; // set once in main()
final H mH = new H();
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
Looper.loop();
}
static class H extends Handler {
public void handleMessage(Message msg) {
System.out.println("msg "+msg.what);
}
}
ActivityThread() {
System.out.println("构造ActivityThread");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int count =0;
while(count <10){
System.out.println("构建message"+count);
Message msg = new Message();
msg.what = count;
mH.sendMessage( msg );
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
}
为了模拟 handler sendMessage 给ActivityThread的主线程, 我们在 ActivityThread 的构造函数里, 创建一个子线程, 并用关联主线程的handler发送消息到主线程的消息队列。
为模拟ActivityThread 的启动过程 再增加一个Main.java
package com.android;
public class Main {
public static void main(String[] args) {
// write your code here
ActivityThread.main( args);
}
}
在android 源码中, 是用反射的方式调用ActivityThread 的main 函数, 这里我们为了方便 直接从Main.main 来启动。
参考资料:
1.《深入理解Android内核设计思想》 林学森
2. https://blog.csdn.net/zhangke3016/article/details/75923323