在android开发中可谓随处可见,不论你是一个刚开始学习android的新人,还是昔日的王者,都离不开它。关于
哇哈哈哈,不要打我。为了不占用篇幅,想必识标题来者理当熟悉。若有不明之处且看其他偏基础点的教程便可。
大王,且先随我看小的从网上盗来的一张图。handler发送Message(消息)至MessageQueue(模拟队列),由Looper(循环器)不断循环取出。然后通知Handler处理。这便是整个的消息机制。没有多复杂。
先说ThreadLocal的作用是不同的线程拥有该线程的变量,同名对象不会被受到不同线程间相互使用出现异常的情况。
即:你的程序拥有多个线程,线程中要用到相同的对象,但又不允许线程之间操作同一份对象。那么就可以使用ThreadLocal来解决。它可以在线程中使用mThreadLocal.get()和mThreadLocal.set()来使用。若未被在当前线程中调用set方法,那么get时为空。
在Looper中是一个静态变量的形式存在,并在每个线程中拥有的Looper对象,没有则为空。
如若还不明白可单独做了解,弄明白这个是必须的,否则后面会云里雾里。不知为何hanlder可以做到跨线程消息切换。我姑且当做读者已熟悉这点。
这里Looper是最为重要的一环,我们先来看这个,其余几个对象源码分析的意义不大,后面小节会在消息流程中分析到。就省略了。如果非要纠结解析可以自己去翻阅一下源码即可。
记住了,Looper主要做两件事。1.创建消息队列。 2.循环取队列中的消息分发。后面一个小节会讲什么时候创建,见流程分析。
其中分为在主线程中创建,和子线程创建,但都是借助ThreadLocal来实现跨线程Looper对象的存储。
可以看到loop方法中是一个死循环在不断的取消息。但注意当无消息时循环并不会做无用功,而是阻塞等待消息。
这便是,为什么handler可以做异步的原因了,因为在主UI线程创建的时候,就早已为UI线程创建了一个Looper,并了循环。
注:请思考一个问题,能不能在子线程中直接new handler发送消息?如果不可以?有没有办决?(切莫去搜一下看到某行代码添加完就可以了便不管为什么这样了,应当分析内部原理。)
最后附一张以前学习Hanlder手写笔记,其实这份笔记光看的话,可能对读者没什么很大做用。但对我的帮助很大。我要表达的是一个学习思,像类似这种源码分析最好自己拿笔写写画画,映象会深刻很多。知识过久了会忘记,光靠死记若非,很难过目不忘。自己写一遍就完全不一样了,就算过了许久已淡忘这些,打开自己的笔记看一眼就会明白。而不用从头来学一遍。
用我的理解来解释这种现象是学习的过程中可能坑坑洼洼,掉不少时间。这种笔记会成为最后总结出来的结晶,与脑子里的印象流关联在一起。何必再费力气每次都从头温习,不如直接看以前自己的总结岂不快哉?
从名字上来看,这厮肯定和线程有扯不开的关系。只闻起名还未使用过的同学别担心,我们先说说他的做用,再分析源码的实现。
先思考这样一个场景,我们知道在android中主线程中是不能做复杂的耗时操作。然而可不可以有一种机制是主线程通知子线程来做某件事呢?
注意:这里说的是通知子线程来做某件事,不是说在主线程中另起一个子线程来做某件事。两者是有区别的。
首先的确HandlerThread本身就是一个线程,他的设计可以用来将事件流在不同的线程中进行切换。恰巧Android主线程可以利用它来做一些耗时的操作。
这段代码很简单,我们有两个线程,mainTh做完某些事情以后将启动子线来执行。这些都没有问题,但当mTh1完成任务以后,它想再次回到主线程中告知mainTh怎么办?是不是思瞬间短了。为什么?因为线程总是顺序执行的,而且是并行顺序执行,一旦执行就没有回。
Handler、Looper、Message、MessageQueue出现以后,HandlerThread基于此。再次提醒读者先弄清楚Handler通信机制才能搞明我们下面要分析的。还是这个功能,我们看伪代码。
mHandler发送消息给HandlerThread的Looper进行处理。此时这件事交由子线程来完成。随后子线程做完事情以后将调用mMainHandler来通知主线程中的Looper完成主线程中该有的操作。至此顺利进行了一把线程之间的通信。
HandlerThread继承了Thread所以本质上它就是一个普通的线程。那么其中run方法里创建Looper并了循环队列。整个源码极其简单。前面我的使用场景中就是通过了getLooper方法来获取当前线程中的Looper,所以handler才能在在线程之间将消息灵活的处理。
Handler在原生Java中其实也有办法做线程间通信。只是方法要么不够优雅,要么会造成cpu运算负荷超高或死锁等情况。而且经常因为技术不到位,导致翻车的情况。所以android中的Hanlder通信机制非常巧妙的避开这样的问题,提供一下原生方法参考学习。
rxJava、rxAndroid等,确实它们非常好用和方便,但不代表handler这种原生的对象就可以摈弃。那些优秀框架的实现都离不android原生的特性,如果要往上进阶学习,就不能只是每天看看这里的大神新出一个轮子,那里大厂又开源一个框架,问其原理一概不知,自己去看他们的源码也是云雾朦胧的。这样以来自己的技术深度很难有较大的进步。而如果是先从基础开始早一点摸清他们的套,再去看人家的框架是怎么写的。学习那些新东西是很快的。而我自己就曾经这样的错误,走了很多弯。希望能给各位同学带来帮助。愿君与。
推荐:
网友评论 ()条 查看