Handler是Android提供用于更新ui的一套机制,也是整个Android应用程序消息处理的机制。Android在设计的时候,封装了一套消息创建,传递,处理机制,如果不遵循这套机制就不能更新ui,会抛出异常信息。有的同学觉得Hander就一个线程切换发消息的作用,而且早就被取代了,没必要学了。其实不然,Handler尤为重要。
Handler的设计是源于生活的,就好像我们城市的人每天上下班。地上的人上班做公交,但是公交运载能力有限,那么一部分已就需要下地铁去乘地铁,乘完了地铁再上去。那么对应我们Android程序就是主线程处理任务能力有限,因为需要在较短的时间内去响应用户,需要将一部分耗时的任务转入地下(即子线程)。等子线程处理完成,需要将处理的结果再次运送到地上(即主线程),那么这个送上送下的地铁电梯传输,就是Handler来做管理。
理解工作原理
Looper就像传送带传送消息,handler通过send/post方法,将货物送上传送带,这些货物就是message,排成messageQueue。当Looper.loop()调用,就是给传送带插上了电,无休止地转动,当传送到那一头了,就通过handler.dispatch()方法传递给需要货物的地方。
源码过程
首先,当Handler调用sendMessage/post时,都会去调用sendMessageAtTime()方法,或许延时,或许不延时,然后调用enqueueMessage(),里面调用的是queue.enqueueMessage()。
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue中的enqueueMessage就是让message放入到消息队列中。
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
消息队列里有消息了,那么谁来取呢?怎么呢?那就要从Looper.loop()方法里面找了。
loop()方法省略版代码:
public static void 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;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
}
msg.recycleUnchecked();
}
}
在loop()方法中执行 for (;;) {}无限死循环,在这个死循环中持续调用queue.next(),不断检测messageQueue是否有message插入队列,若有即调用了msg.target.dispatchMessage(msg),这个target即为发送msg的target。如果什么时候取到的消息为null就说明消息队列调用了quit()或被释放,此时loop()里面死循环就return掉了。
再进入handler的dispatchMessage方法中,最后调用了handleMessage()这个接口方法,即可在任意需要的地方进行回调获取到这个msg。
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public interface Callback {
boolean handleMessage(@NonNull Message msg);
}
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(@NonNull Message msg) {
}
至此,handler传送消息的整个流程就走完了。
关于Handler消息处理过程总结:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2.handler调用sendMessage,再调用messageQueue.enqueueMessage将消息插入到消息队列。
3、Looper.loop()会让当前线程进入一个无限循环,不断从MessageQueue消息队列中使用queue.next()读取消息,获取非空的消息后回调msg.target.dispatchMessage(msg)方法。最终调用的是handler的handleMessage()回调方法。
其他代码:
public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
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;
mCallback = callback;
mAsynchronous = async;
}
Handler的构造函数,在构造函数中初始化了一个Looper 和 MessageQueue。
Looper调用prepare,创建了一个looper,保存到了sThreadLocal对象中,然后调用myLooper() 从sThreadLocal对象中获取looper。
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
ThreadLocal中get()与set()方法:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
通过Thread.currentThread()获取当前线程,从当前线程获取线程的threadLocals属性,它是一个ThreadLocal.ThreadLocalMap对象,然后从该对象中存取元素。
通过Looper.prepare()创建的looper是保存在当前线程的threadLocals中,不同线程调用Looper.prepare()创建looper会将looper对象保存在对应的线程当中,保证了不同线程之前的looper实例单独保存,互不影响。
looper调用prepare的时候,创建Looper对象,在构造方法里创建了MessageQueue对象,并保存在looper中,也是单独一份。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
手写Handler实现:
手写Handler机制,主要需要实现四个类,Handler、Looper、Message、MessageQueue。
1.先定义好Message类代码,设置Message属性以及回收复用。
public final class Message {
/**
* Message类处理静态 message 消息池缓存
*/
private static LinkedList<Message> cache;
/**
* 缓存池大小
*/
private static final int CACHE_SIZE = 30;
public Runnable callback;
static {
cache = new LinkedList<>();
for (int i = 0; i < CACHE_SIZE; i++) {
cache.addLast(new Message());
}
}
public String what;
public long when;
public Object arg1;
public Object arg2;
public Handler target;
/**
* 获取缓存池消息,不为空从缓存池中取,否则新创建Message
*
* @return
*/
public static Message obtain() {
if (!cache.isEmpty()) {
return cache.removeFirst();
}
return new Message();
}
/**
* 消息使用完之后添加入缓存池,并且将所持有属性清空
*/
public static void addCache(Message message) {
if (message == null) return;
if (cache.size() >= CACHE_SIZE) return;
message.when = 0;
message.what = null;
message.arg1 = null;
message.arg2 = null;
message.target = null;
}
}
2.Handler类代码,持有looper,并定义好send/post方法。
public class Handler {
private Looper mLooper;
public Handler() {
this.mLooper = Looper.getMainLooper();
}
public void sendMessage(Message message) {
message.when = System.currentTimeMillis();
message.target = this;
mLooper.getmQueue().enqueueMessage(message);
}
public void post(Runnable runnable) {
Message message = Message.obtain();
message.callback = runnable;
message.when = 0;
message.what = null;
sendMessage(message);
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //postMessage类型
msg.callback.run();
} else {
msg.target.handleMessage(msg); //sendMessage类型
}
}
public void handleMessage(Message msg) {
}
public Looper getLooper() {
return mLooper;
}
public void setLooper(Looper looper) {
mLooper = looper;
}
}
- MessageQueue类,定义好Node节点,并处理完善消息入队,出队逻辑。
public class MessageQueue {
/**
* 队列大小
*/
private int size;
/**
* 队列头节点
*/
private Node head;
/**
* 队列尾节点
*/
private Node tail;
public MessageQueue() {
size = 0;
head = null;
tail = null;
}
/**
* 消息队列的有序队列
*/
private static class Node {
Node pre;
Node next;
Message message;
public Node(Message message) {
this.message = message;
}
}
private boolean insertToLinkTail(Node node) {
if (head == null) {
head = tail = node;
return true;
}
Node p = head;
while (p != null) {
if (p.message.when > node.message.when) {
break;
}
p = p.next;
}
if (p == head) {
//头部
p.pre = node;
node.next = p;
head = node;
return true;
} else if (p == null) {
//尾部
tail.next = node;
node.pre = tail;
tail = node;
return true;
} else {
//中间
Node pre = p.pre;
pre.next = node;
node.next = p;
node.pre = pre;
p.pre = node;
return true;
}
}
/**
* 每次获取头结点
* @return
*/
private Node removeFromLinkHead() {
if (head == null) return null;
Node p = head;
Node newHead = head.next; //第二个节点
if (newHead == null) {
head = tail = null; //将唯一节点取完,头尾节点为空
} else {
newHead.pre = null;
head = newHead; //取出头节点,newHead成新的头节点
}
return p;
}
/**
* 添加消息到 MessageQueue 中
* @param message
* @return
*/
public boolean enqueueMessage(Message message) {
synchronized (this) {
if (insertToLinkTail(new Node(message))) {
size++;
return true;
}
}
return false;
}
/**
* 取出头节点并返回message
* @return
*/
public Message next() {
synchronized (this) {
Node node = removeFromLinkHead();
if (node == null) {
return null;
}
size--;
return node.message;
}
}
public int getSize() {
synchronized (this) {
return size;
}
}
}
4.Looper类,Looper持有MessageQueue,调prepare创建looper,调loop在循环中取消息。
public class Looper {
public static ThreadLocal<Looper> threadLocal;
private MessageQueue mQueue;
private volatile boolean nativeEpoll = false;
private static Looper mMainLooper;
static {
threadLocal = new ThreadLocal<>();
}
private Looper() {
mQueue = new MessageQueue();
}
public static Looper getLooper() {
return threadLocal.get();
}
public static Looper getMainLooper() {
return mMainLooper;
}
public MessageQueue getmQueue() {
return mQueue;
}
public static void prepare() {
if (threadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
threadLocal.set(new Looper());
}
public static void prepareMain() {
prepare();
mMainLooper = getLooper();
}
public static void loop() {
final Looper me = threadLocal.get();
if (me == null) {
throw new Error("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;
for(;;) {
//取出消息进行分发
Message message = queue.next();
if (message != null) {
try {
message.target.dispatchMessage(message);
//处理完消息,放入缓存池中
Message.addCache(message);
} catch (Exception exception) {
}
}
//退出循环取消息
if (me.nativeEpoll) {
return;
}
}
}
public void setNativeEpoll() {
nativeEpoll = true;
}
}
执行测试:
object HandlerTest {
fun handleMessage() {
Looper.prepareMain()
val handler: Handler = object: Handler() {
override fun handleMessage(message: Message?) {
message?.let {
if (message.callback != null) {
message.callback.run() //如果是post类型,执行runnable的run方法
} else {
println("收到what: " + it.what + "收到arg1" + it.arg1 + "收到arg2" + it.arg2)
}
}
}
}
Thread {
handler.sendMessage(Message.obtain().apply {
what = "这里what数据"
arg1 = "这是arg1数据"
arg2 = "这是arg2数据"
})
handler.sendMessage(Message.obtain().apply {
what = "再发送what数据"
arg1 = "再发送arg1数据"
arg2 = "再发送arg2数据"
})
Thread.sleep(4000)
handler.post(Runnable {
println("执行了handler post任务")
})
Looper.getMainLooper().setNativeEpoll() //停止循环获取消息
}.start()
Looper.loop()
}
}
调用测试
HandlerTest.handleMessage()
打印:
收到what: 这里what数据收到arg1这是arg1数据收到arg2这是arg2数据
收到what: 再发送what数据收到arg1再发送arg1数据收到arg2再发送arg2数据
执行了handler post任务
参考:
https://www.jianshu.com/p/9564c5d4a64e