handler机制详解
来源:互联网 发布:走路领红包软件 编辑:程序博客网 时间:2024/05/16 14:44
Handler详解
- 在ui线程中我们之后new Handelr()然后实现子线程和主线程的通讯是没有问题的。那是因为在ActivityThread类中调用了Loop.Preapre();和Looper.loop()方法 现在我们在子线程模拟这个过程
- 在子线程中
代码如下
new Thread(){
public void run() {Handler handler=new Handler(); };}.start();
- 发现异常
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
- 我们只是写了new Handler()就报了一个异常,因此我们查看下构造方法
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
} - 构造方法中先调用Looper.myLooper() ,之后判断是否为null,如果为null 抛出异常 因此我们可以肯定,这里的mLooper肯定为null
- 因此我们得查看Looper.myLooper()方法是怎么工作的
- Looper.myLooper(); 源码
public static Looper myLooper() {
return sThreadLocal.get();
} - 这里引入了一个sThreadLocal.get();本地线程的get方法,我们继续查看get()返回的是什么?
- 首先我们产看ThreadLocal类的功能
Implements a thread-local storage, that is, a variable for which each thread
has its own value. All threads share the same {@code ThreadLocal} object发现ThreadLocal就是给线程储存了一个共享的对象
接下来我们看一看Looper.Prepare() 方法完成了什么
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));
}- 可以看到sThreadLocal将我们的Looper对象存放到了线程中
- 这也就能解释当我们new Hander()的时候,抛出异常,是因为直接Looper.myLooper();拿到的为空,如果我们prepare()的话 ,就给sThreadLocal存放了一个looper,因此也就不为null了,通过源代码,也可以发现一个线程只能有一个looper和Message,但是可以有多个handelr
- 那么looper.loop()方法的作用是什么呢?是让消息泵循环起来,去Messagequeue中读取消息,不loop起来的话 sendMessage()无效
` 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;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();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 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycle();}
}`
- 大家看源代码可以看到 Looper.loop()首先拿到自己的Looper,之后拿到消息队列,也就是MessageQueue,因此可以看到MessageQueue在Looper中,因此一个线程只能有一个Looper,也只能有一个MessageQueue
- 之后是一个死循环,不断的调用msg.next();可能被阻塞,类似Socket的服务器端,之后分发出去
接着我们看sendMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) { msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis); }
- 最终将消息存放到了消息队列中 ,looper的话就直接从MessageQueue死循环读取
总结
- handler.sendMessage()的功能是将Message()放到Hander中的MessageQueue中
- Looper.prepare()是将Looper绑定到本线程ThreadLocal中
- new Handelr()的时候 获得了ThreadLocal中绑定的Looper
- Looper.loop()的时候,是死循环遍历MessageQueue,拿到消息给了msg.target,这个target指的就是发送消息的那个handelr
- 一个thread中只能有一个Looper和MessageQueue,但是可以多个handler,因为在handler.sendMessage()的时候,Message被放到messagequeue的时候,已经和发送的hanlder绑定了,之后再loop的时候是msg.target.dispatch分发出去
- handler和Looper共用的是MessageQueue
- Messagequeue是Looper的一个成员变量
- ThreadLocal 是保存线程共享的内容的,这里用来保存了Looper
- 发现异常
0 0
- Android Handler机制详解
- Android Handler机制详解
- handler机制详解
- Handler 机制详解
- Handler机制详解
- Handler机制详解
- handler机制详解
- Handler消息机制详解
- 详解handler机制
- 详解handler机制
- Handler机制详解
- handler机制详解
- handler机制详解
- handler消息机制详解
- Handler机制详解
- anroid Handler机制详解
- Handler机制(详解)
- Handler机制详解
- GoLang notes
- Java HashSet和HashMap源码剖析
- Java 理论与实践: 处理 InterruptedException
- WPF之HierarchicalDataTemplate
- Python 核心编程笔记_Chapter_3 Note_1_语句和语法_赋值与变量_标识符
- handler机制详解
- 魅族 魅蓝note2 PRO5 华为荣耀6 6P 部分log不显示,不打印,不输出
- RocketMQ中的批处理
- 20160524acm周赛
- 提升linux下tcp服务器并发连接数限制
- Session,Cookie,记住登陆状态
- 系统调用,上下文切换及中断概念的汇总
- Nginx与Lua执行顺序
- Log4j2 自定义 Appender