第一次写文章,有点小紧张,担心自己的辞藻不够华丽,引得各位看官砸了自己的小店。做点营生不容易,还望各位看官多多包涵。好了,开始咱们今天的交流吧!请自觉备好板凳,小店比较穷,还没布置板凳~~~·
首先咱们先从google对它的定义出发:Handler允许咱们发送/处理Message,同时也能发送/处理与MessageQueue关联的任务。每一个Handler对象与一个的线程以及此线程对应的MessageQueue相关联。当创建Handler时,必然创建新的线程以及与该线程相关的MessageQueue。
MessageQueue使用SparseArray,类似于链表的数据结构。
一个消息的产生与处理:咱们通过Handler提供的接口,可以向MessageQueue发送消息和任务,MessageQueue则会通过put(),将message/runnable压入队列。既然是Queue,那么肯定遵循FIFO(先进先出),也肯定提供了弹出函数next()。既然都弹出来了,那么谁来接受那?没错,就是咱们重写的handleMessage()。会有那么简单吗?咱们,仔细的捋一下:Handler通过send/post发送消息/任务到MessageQueue,MessageQueue将他们全部put进去,他们按入队顺序排列,然后通过MessageQueue.next()将他们踢出队列,最后到了咱们的handleMessage()中。是不是觉得有点不合理?咱们发消息是为了处理,不是为了让MessageQueue存储,所以Queue应该保持干净整洁,那么是谁当了清洁工?。。。没错,那就是Looper!多么任劳任怨啊,咱们还把他忘了,汗!不过,压轴的都是重量级的。Looper负责监视MessageQueue的装载,一旦Queue有了要处理的消息,它就立即调用mQueue.next(),并将消息通过handler.dispatchMessage(msg)发送到handleMessage()中。
既然Handler和他的小伙伴帮了咱们那么大的忙,咱们是不是应该更深入的理解他们那?同意的买块雪糕,咱们继续,我请客,不同意的掏钱!!!!!
1.请问Handler,为什么你有那么多的构造方法啊?搞得奴家不知道用哪个好呐。Handler卒。。。其实,handler的构造方法与运行Handler的线程有关。前方高能:默认的工作线程是不能进行UI更新的,而UI线程因为负责UI的更新,所以它不能进行一些耗时操作。(其实多体谅一下,毕竟UI更新是件挺耗时的工作,再让人家多做,咱们情何以堪啊!)UI线程默认是有Looper的,而工作线程是没有Looper的。再看下Handler的构造方法。参数列表不带Looper的,默认使用创建它的UI线程的Looper,所以handleMessage()是运行在UI线程的,可以进行UI的更新;反之,参数列表带Looper的,运行在创建Looper的那个线程,又因为,一个线程只能有一个Looper,所以不可能是UI线程,因此不能在handleMessage()进行UI的更新。细心的咱们应该看出一点端倪,handler的创建离不开Looper。因此,只有调用了Looper.prapare()的线程中,才能创建Handler.
2.Looper那么强大,咱们更应该知道它是怎么工作的,要不对得起死去的Handler吗?咱们从源码一步步跟进吧。看源码前,咱们先了解一些额外的知识。
ThreadLocal:为解决多线程共享同一资源时产生的并发问题,而创建的工具类,更确切的说是一种策略,被称为线程的局部变量。它可不是一个线程!!!它是如何工作的那? 当线程使用ThreadLocal维护变量时,Threadlocal为每个使用 线程的局部变量 的线程提供独立的变量副本,所以每个线程都可以独立的改变自己的副本,而不会影响其他线程对应的副本。即:每个线程对共享数据进行存储,通过变量的形式,解决并发问题。 那么是谁对资源进行存储的那?答案是ThreadLocalMap,一个采用懒汉式,有且至少有一个条目放入其中时才会创建的弱引用。
代码:public static void prepare() {
prepare(true);
}
private static void prepare(booleanquitAllowed) {
if(sThreadLocal.get() !=null) {
throw newRuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));// Looper为ThreadLocal维护的变量,被ThreadLocalMap存储。
}
private Looper(booleanquitAllowed) {
mQueue=newMessageQueue(quitAllowed);// 创建消息队列
mThread= Thread.currentThread();// 当前所处的线程
}
public static void loop(){// 既然叫loop,那肯定会有循环
.....
for(;;){//果然不出我们所料
Message msg = mQueue.next();//通过JNI调用nativePollOnce()弹出消息,
msg.target.dispatchMessage(msg)://将消息发送到handleMessage()中进行处理。
}
}
其实,若想对Handler机制有更深的理解,应该着眼于它的使用。
好了,我对Handler的原理理解就是这样的了,如果有什么不对,或者不清楚的地方,欢迎大家一起交流,共同进步。
下篇就IntentService,一个集合Handler与HandlerThread的服务,来更详细的理解Handler.