您的位置:首页 > 移动开发 > Android开发

Android Handler源码解析

2016-06-30 08:59 656 查看
上一篇的地址为 Android Looper源码解析

一、
4000
讲解:

Android中的Handler是用来接受消息,并处理消息中的内容。它可以看成是一个线程的接口,当给它发送消息时,其对应的线程便会处理消息。

Google的介绍为:

A Handler allows you to send and process {@link Message} and Runnable
objects associated with a thread's {@link 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允许你发送一个消息或者Runnable代码块给其关联的线程的消息队列,每个Handler的示例都关联着其线程和线程的消息队列。即当你创建一个新的Handler时,它关联了创建的线程和其线程中的消息队列,之后,它就可以发送一个消息或者Runnable代码块给其关联的消息队列。当消息队列弹出对应消息时,Handler也会执行它

带着问题去看源码是最好的方法,那么我们的问题是:

  1、为什么每个Handler初始话时在哪个线程就是哪个线程的接口?
  2、sendMessage如何执行的? 
  3、 Handler的post方法怎么来执行的?
4、obtain方法为什么比直接new一个Message更好?

二、
1、先解决第一个问题,为什么在哪个线程初始化就是哪个线程的接口?
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
其调用了
public Handler(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 that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
我们来看下面的几行代码,首先得到当前线程的Looper对象,然后执行mQueue = mLooper.mQueue,得到当前线程的MessageQueue对象。

2、第二个问题,sendMessage如何执行的
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(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(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我们将sendMessage()方法调用的顺序打印出来,可以看出,其最后调用的是私有的enqueueMessage()方法,即先得到此时系统的时间,然后得到自己绑定的MessageQueue,然后调用msg.target = this;将Message的target指向自己。最后,调用MessageQueue的enqueueMessage()方法进入消息队列。

3、第三个问题,Handler的post方法怎么来执行的?

Handler的post的执行顺序其实跟上面的sendMessage()执行顺序基本一样,只不过第一个方法中调用了getPostMessage(Runnable r)将Runnale生成为Message:
public final boolean post(Runnable r)
{
return  sendMessageDelayed(getPostMessage(r), 0);
}


4、第四个问题,obtain方法为什么比直接new一个Message更好?
/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
*  If you don't want that facility, just call Message.obtain() instead.
*/
public final Message obtainMessage()
{
return Message.obtain(this);
}
可以看出来,其调用了Message类的obtain(this)方法,从Message全局的消息池中获取实例,这样可以充分的做到资源重用,而不用再自己想使用时在重新new一个出来。

看来,Handler只是接收Runnable并将其封装成消息或者直接接受消息然后发送给其绑定的线程的消息队列,下一步我们会继续分析MessageQueue和Message的源码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: