Handler知识整理学习(一)

之前用hexo+github来对自己学习的知识做一个记录和整理,但是发现图片上传,文章管理等等略有麻烦,所以在也搭一个小窝吧 :)

Handler

关键的概念以及问题的解释

MessageQueue:消息队列,按顺序存放消息实体,由单链表实现。
ThreadLocal:一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储之后只能在指定的线程中可以获取到存储的数据,其他线程无法获取。

Q:系统为什么不允许在子线程中访问UI?
A:因为Android中的UI不是线程安全的,多线程并发访问UI会导致不可预测的后果。那为什么不给UI控件加上锁机制呢?第一锁机制会使得UI访问变得复杂。其次会降低UI访问的效率。于是使用了简单高效的单线程模型来处理UI操作。

Handler运行流程

首先,梳理一下Hnadler的运行流程:

  • 新建Handler,通过sendMessage或者post发送消息,Handler调用sendMessageAtTime将Message交给MessageQueue
  • MessageQueue.enqueueMessage方法将Message以链表的形式放入队列中
  • Looper的loop方法循环调用MessageQueue.next()取出消息,并且调用Handler的dispatchMessage来处理消息
  • 在dispatchMessage中,分别判断msg.callback、mCallback也就是post方法或者构造方法传入的不为空就执行他们的回调,如果都为空就执行我们最常用重写的handleMessage。

如图:

Handler知识整理学习(一)_第1张图片
handler.png

官方API对Hnadler的说明

看看官方api对Handler的说明:

“A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue. ”

一个Handler 允许你发送和处理与线程MessageQueue相关联的Message 和Runnable对象。每个Handler 实例和单个线程和线程的消息队列相关联。当实例化一个Handler的时候,它就承载在一个线程和消息队列的线程,这个Handler可以把Message或Runnable压入到消息队列,并且从消息队列中取出Message或Runnable,进而操作它们。

There are two main uses for a Handler:
(1) to schedule messages and runnables to be executed as some point in the future; and(2) to enqueue an action to be performed on a different thread than your own.

Handler主要有两个作用:1.在工作线程中发送消息 2.在UI线程中获取、处理消息.

  • Post:Post允许把一个Runnable对象入队到消息队列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。
  • sendMessage:sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)。

View.post

View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。

Handler.post

这里重点学习一下post方法。
先来看看post()源码:

public final boolean post(Runnable r)  
{  
   return  sendMessageDelayed(getPostMessage(r), 0);  
} 

继续查看getPostMessage():

private static Message getPostMessage(Runnable r) {  
    Message m = Message.obtain();  
    m.callback = r;  
    return m;  
}

Runnable被封装成Message.callback,最后来看看dispatchMessage():

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

在dispatchMessage中,对post的msg的callback不为空的情况,调用handleCallback方法

private final void handleCallback(Message message) {  
message.callback.run();  
}  

handleCallback()方法里面直接调用用之前Runnbale里面的run()方法。

sendMessage的源码就不再贴了,从源码上看本,这两者没有多大的区别。
post方法相对实现起来更方便一些。

此外出现post时,run方法不执行的情况,有可能是而是我们初始化对象和这个对象的作用域引起的问题,我们如果不在最开始定义runnable对象的时候就初始化,那就会导致在我们dispatchMessage的时候实际上看到的runnable是null,导致run方法不执行。

后记

Handler的学习先整理到这,有机会继续补充写第二部分。

参考资料:

Android开发艺术探索-任玉刚
google官方api说明

你可能感兴趣的:(Handler知识整理学习(一))