Android消息处理机制、Hanlder机制(Handler、Looper、MessageQueue和Message)

·前言

长久以来,我使用Hanlder仅限于它的基本使用:post 和 sendMessage

而对于Hanlder的原理和消息处理机制并不清楚。找了两篇比较深入的博客:

http://www.cnblogs.com/angeldevil/p/3340644.html  AngelDevil的博客

http://blog.csdn.net/amazing7/article/details/51424038  amazing7的博客

学习了一下,又对照了源码,小有收获,俗话说“好记性不如烂笔头”,所以做一下笔记,总结一下,方便以后回顾。

·Android是消息驱动的

AngelDevil的博客的博客中指出Android是消息驱动的,这一点,看一下类ActivityThread就一目了然了。


public final class ActivityThread {
    
    //……
    
    final ApplicationThread mAppThread = new ApplicationThread();
    
    //……
    
    final H mH = new H();
    
    //……
    
    final Handler getHandler() {
        return mH;
    }
    
    //……
    
    private class ApplicationThread extends ApplicationThreadNative {//……}
    //……
    
    private class H extends Handler {//……}
    
    //……
     
    public static void main(String[] args) {
        
        //……
           
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

}

源码中找到了入口方法main(),从Looper.prepareMainLooper();这一行看起,到Looper.looper();
我们都知道,main()方法是程序的入口,方法里面就是主线程,从Looper.prepareMainLooper()到Looper.looper(),表明开启了轮询器,其间不断的进行消息的发送和处理,所以说Android确实是“消息驱动的”。
ActivityThread thread = new ActivityThread():
表明在入口方法main()中创建了一个ActivityThread自己的对象,并通过代码
if (sMainThreadHandler == null) {
     sMainThreadHandler = thread.getHandler(); 
}
获得ActivityThread内部的Handler,而ActivityThread源码中有这这几行代码:
   
 final ApplicationThread mAppThread = new ApplicationThread();
    final H mH = new H();
    final Handler getHandler() {
        return mH;
    }
    private class ApplicationThread extends ApplicationThreadNative {//……}
    private class H extends Handler {//……}

getHanlder就是H,H继承于Handler,而H(extends Handler)的handleMessage(){}中接受的都是一些系统消息。

也就是说,在主线程中,有一个Looper轮询器,在Looper.prepareMainLooper()和Looper.loop()之间创建了ActivityThread实例,并获得了ActivityThread内部的Handler实例,相当于在Looper的两个方法中间创建了Hanlder。Android正是通过这个Handler进行的消息传递。

·Looper轮询器

下面看一下Android源码中提供的Looper典型使用

/**
  * ……
  * This is a typical example of the implementation of a Looper thread,
  * using the separation of {@link #prepare} and {@link #loop} to create an
  * initial Handler to communicate with the Looper.
  *//这是一个Looper线程实现的典型案例,使用Looper.prepare()和Looper.loop()中间被隔开的部分创建
  *//和初始化Handler,以便与Looper进行通信。
  * 

  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }
  */public final class Looper {//……}

正好与上面ActivityThead类中的用法相对应,只不过一个在主线程中(main()中),一个在子线程中。其本质用法是一样的。
下面是Looper的源码:
/**
  * 这个类用于为一个线程运行一个消息循环。默认的线程并没有一个消息循环与它们相关联;
  * 在线程中调用此类的prepare()方法来创建一个消息循环并且运行这个循环,然后调用Loop()
  * 来使消息循环处理消息直到这个循环被终止。
  *
  * 大多数与消息循环的交互是通过Handler类来实现的。
  *
  * 这是一个Looper线程实现的典型案例,通过使用Looper.prepare()和Looper.loop()中间被隔开的部分创建
  * 和初始化Handler,以便与Looper进行通信。
  * This is a typical example of the implementation of a Looper thread,
  * using the separation of {@link #prepare} and {@link #loop} to create an
  * initial Handler to communicate with the Looper.
  *
  * <pre>
  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }</pre>
  */
public final class Looper {


    private static final String TAG = "Looper";

    // sThreadLocal.get() 将返回null,除非你已经调用了prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
	
	
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;

    private Printer mLogging;

     /** 将当前线程初始化为一个轮询器(looper)。(也就是在当前线程中维持一个轮询器)
      * 这样你就可以创建handler,handler之后会在开始轮询之前引用这个轮询器。要确保在调用
      * 这个方法后调用{@link #loop()}方法,并且调用{@link #quit()}方法结束它。
      */
    public static void prepare() {
        prepare(true);
    }

	/**
	 * 这个方法中创建了Looper对象,并与线程关联
	 *
	 */
    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));
    }

    /**
     * 将当前线程初始化为一个轮询器(looper), 并标记为一个应用的主轮询器。
     * 应用的朱轮询器由Android环境创建(在ActivityThread#main()中被调用),
	 * 所以你不需要自己调用这个方法。可以看:{@link #prepare()}。
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    /**
     * 返回应用的主轮询器(looper),它存在于应用的主线程。
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

    /**
     * 在当前线程中运行(轮询)消息队列。确保调用{@link #quit()}方法结束循环。
     */
    public static void loop() {
		
		//获取当前线程的Looper
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
		//获取Looper中的消息队列
        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);
            }

			//###通过message的target(Handler)分发处理消息
            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.recycleUnchecked();
        }
    }

    /**
     * 返回与当前线程关联的Looper对象,如果当前线程未关联Looper,返回null。
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

    /**
     * 返回与当前线程关联的 {@link MessageQueue} 对象。这个方法必须在运行着Looper的线程中
     * 调用,否则会抛出空指针异常。
     */
    public static @NonNull MessageQueue myQueue() {
        return myLooper().mQueue;
    }

	/**
	 * 私有构造方法。
	 * 其中创建了消息队列(MessageQueue)。获取了当前线程。
	 * 在prepare()方法中调用创建实例。可以通过myLooper()方法获取looper实例。
	 */
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

   

    /**
     * 停止当前轮询器。
     * <p>
     * 使{@link #loop} 停止,不再处理消息队列中的任何消息。
     * </p><p>
     * 轮询器停止(轮询)后,任何尝试发送消息到队列都将失败。
     * 例如,{@link Handler#sendMessage(Message)} 方法将会返回false。
     * </p><p class="note">
     * 使用这个方法可能不安全,因为一些消息可能在轮询器结束之前没有被分发处理。
     * 考虑使用{@link #quitSafely} 代替,以确保所有待完成的工作能被井井有条地完成。
     * </p>
     */
    public void quit() {
        mQueue.quit(false);
    }

    /**
     * 安全停止当前轮询器。
     * <p>
     * 一旦消息队列中所有余下的到期的消息被分发处理,就使循环{@link #loop} 停止。
     * 然而,还有一定时间到期的延迟消息不会在循环终止之前分发处理。
     * </p><p>
     * 轮询器停止(轮询)后,任何尝试发送消息到队列都将失败。
     * 例如,{@link Handler#sendMessage(Message)} 方法将会返回false。
	 * </p>
     */
    public void quitSafely() {
        mQueue.quit(true);
    }

    /**
     * 获得与这个轮询器关联的线程。
     *
     * @return 轮询器的线程
     */
    public @NonNull Thread getThread() {
        return mThread;
    }

    /**
     * 获得轮询器的消息队列。
     *
     * @return 轮询器的消息队列
     */
    public @NonNull MessageQueue getQueue() {
        return mQueue;
    }
	
	//......

}
从Looper源码中可以得知:
① Looper的构造方法被私有化, 只能Looper能创建自己对象,而且在构造方法中,创建MessageQueue实例,获得当前线程。
在Looper的prepare()方法中创建了一个Looper对象,并且设置给sThreadLocal(ThreadLocal<Looper>),sThreadLocal.set(new Looper(quitAllowed));
③ Looper.prepare()在 一个线程中只能实例化一次,否则将抛出异常
④ Looper的loop()方法中,要从当前Looper(Looper me = myLooper())中获得它的MessageQueue,并循环取出Message进行处理。
    *myLooper()方法获得设置给ThreadLocal中的Looper,sThreadLocal.get()。
Looper的prepare()方法中调用了ThreadLocal的set()方法,myLooper()中调用了ThreadLocal的get()方法,下面看ThreadLocal的get()和set()方法:
public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null)
            return (T)e.value;
    }
    return setInitialValue();
}

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

//获取线程t的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}
//为线程t的(ThreadLocalMap)threadLocals赋值
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
set()方法将looper设置给当前线程,get()方法从当前线程中获得looper。
小结一下:
①Looper通过prepare()方法,创建Looper自己的对象,同时创建了一个消息队列(MessageQueue),并通过ThreadLocal的set()方法设置给了当前线程(其实是当前线程的ThreadLocalMap的Entry的value);
②Looper通过myLooper(),其实是通过sThreadLocal(ThreadLocal<Looper>)的get()方法从当前线程中获得Looper。
③Looper的loop()方法中,获得当前线程的Looper,并获得Looper的MessageQueue,然后循环取出消息,交给Message的target(发送Message的Hanlder)分发处理。
    *我们都知道Activity属于应用的主线程,在Activity中创建的Hanlder(不指定Looper),其实是在上面main()中的Looper.prepareMainLooper()和Looper.loop()之间,与Looper的典型使用,一模一样。

Hanlder

看一下Hanlder的构造方法:

下面是两个主要构造方法的源码:
 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;
    }
    
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
从Handler(Callback callback, boolean async)的mLooper = Looper.myLooper()处往下看,这是要获得当前线程的Looper,如果mLooper == null,就抛出运行时异常
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(//不能在没有调用Looper.prepare()的线程里创建handler.
"Can’t create handler inside thread that has no called Looper.prepare()");
}
这两个构造方法中,一个是从当前线程取出与之关联的Looper,另一个要传入一个Looper,所以说要在线程中创建Handler实例,需要一个Looper。

Handler发送消息

下面是Handler发送消息内部调用流程

发现Handler发送消息方法中最终调用的是sendMessageAtTime()方法,下面是消息发送的源码:
public final boolean sendMessage(Message msg)
{
    return sendMessageDelayed(msg, 0);
}

public final boolean sendEmptyMessage(int what)
{
    return sendEmptyMessageDelayed(what, 0);
}


public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageAtTime(msg, uptimeMillis);
}

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);
}

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

public final boolean postAtTime(Runnable r, long uptimeMillis){
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}

public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

public final boolean postDelayed(Runnable r, long delayMillis){
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

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

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

private static void handleCallback(Message message) {
    message.callback.run();
}
我们可以看出,
① 其他发送消息的方法最后都调用了sendMessageAtTime()方法,然后返回了enqueueMessage()方法
② 发送空消息(sendEmptyMessage)时,其实创建了消息实体,只是没有消息内容(数据)
③ post系列方法看似发送的是Runnable,但最终调用sendMessageAtTime(Message msg, long uptimeMillis),而这个方法第一个参数是一个Message,其实发送的还是Message,看一下getPostMessage()会发现,里面创建了消息,并将Runnable赋值给message的callback。而在handler的dispatchMessage()中调用了(if (msg.callback != null))handleCallback(msg),而handleCallback()中运行了Runnable(message.callback.run())


下面看一下此方法源码:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
在这个方法中需要注意
    1.msg.target = this
        这是将当前handler赋值给了Message的target,而在之后Looper的loop()方法中,从MessageQueue中循环取出Message(msg)后,
    调用msg.target.dispatchmessage(msg)来处理这个消息。
    2.queue.enqueueMessage(msg, uptimeMillis)
        queue由sendMessageAtTime方法传传参而来,最终来自handler构造方法的myLooper()方法,也就是当前handler所在线程的Looper管理的MessageQueue。
    也就是说,handler发送消息到当前线程的Looper的消息队列里。

Message
下面看一下Message部分的源码:
public final class Message implements Parcelable {
    
    public int what;
 
    public int arg1; 

    public int arg2;

    public Object obj;
	
	//......
    
    /*package*/ Handler target;
    
    /*package*/ Runnable callback;
    
    // sometimes we store linked lists of these things
    /*package*/ Message next;

    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 50;

    private static boolean gCheckRecycle = true;

    /**
     * Return a new Message instance from the global pool. Allows us to
     * avoid allocating new objects in many cases.从全局池中返回一个新的消息实例。
	 * 使我们在很多情况下避免分配新的对象。
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }

	//......

    /**
     * Return a Message instance to the global pool.回收一个消息放到全局池。
     * <p>
     * You MUST NOT touch the Message after calling this function because it has
     * effectively been freed.  It is an error to recycle a message that is currently
     * enqueued or that is in the process of being delivered to a Handler.
	 * 调用这个方法后你就不能再用Message,因为它已经被有效释放。回收一个正在列队或正在被
	 * 分配给Hanlder的过程中的Message是错误的。
     * </p>
     */
    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }

    /**
     * Recycles a Message that may be in-use.
     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
     */
    void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }

	//......
    
    public void setTarget(Handler target) {
        this.target = target;
    }

    
    public Handler getTarget() {
        return target;
    }

	//......

    /**
     * Sends this Message to the Handler specified by {@link #getTarget}.
     * Throws a null pointer exception if this field has not been set.
     */
    public void sendToTarget() {
        target.sendMessage(this);
    }


	

    /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
	 * 构造器 (但是获得一个Message的首选方式是调用Message.obtain())
    */
    public Message() {
    }

	//......
}
从Message部分源码中可以看出:
    1. 创建Message实例,首选Message.obtain()
    2. Message的target确实是一个Handler,而Message的callback是一个Runnable
    3.Message内部保存了一个全局缓存的消息池,我们可以用obtain从缓存池获得一个消息,Message使用完后系统会调用recycle回收,如果自己new很多Message,每次使用完后不能及时回收,会占用很多内存的。

Handler处理消息

看一下Looper的loop()方法的源码:
public static void loop() {
    final Looper me = myLooper();//获得当前线程的Looper
    if (me == null) {//如果为null,抛出运行时异常("没有Looper;线程中没有调用Looper.prepare()
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."
    }
    final MessageQueue queue = me.mQueue; //从Looper中获得消息队列
    // ……
	//开始无限循环
    for (;;) {
		//不断从消息队列中取出消息(Message)
        Message msg = queue.next(); // might block 可能阻断
        if (msg == null) {
            // No message indicates that the message queue is quitting. 如果没有消息标识(没有
            return;
        }
        //……
		
        try { //msg.target其实是一个Hanlder,Hanlder发送消息时,会把当前这个handler作为target
            msg.target.dispatchMessage(msg);//Hanlder分发消息
        } finally {
            //……
        }
        //……
	
        msg.recycleUnchecked();
    }
}
代码,msg.target.dispatchMessage(msg),表明Message的target处理了消息,也就是发送消息的handler处理了消息(谁发送,谁处理),也是这个Looper所在线程的Handler处理了消息。
所以说,Looper.prepare()中创建了消息队列(MessageQueue),并与当前线程关联;Looper.loop()获得当前线程的Looper并循环遍历其管理的MessageQueue(),用Message自己的target处理消息。这个target就是当前线程Looper两个方法之间创建的handler对象。
我们就知道了,Looper的loop()方法是取出消息并处理消息的场所,而真正处理消息的对象,还是发送消息的handler。
Looper的loop()方法中使用了msg.target.dispatchMessage(msg),也就是Handler的dispatchMessage()方法,下面看一下handler的消息分发处理的源码:
/**
 * Callback interface you can use when instantiating a Handler to avoid
 * having to implement your own subclass of Handler.
 * 实例化一个handler时,为避免必须实现你自己的Hanlder的子类,你可以使用回调接口。
 */
public interface Callback {
    public boolean handleMessage(Message msg);
}
/**
 * Subclasses must implement this to receive messages.//子类必须实现这个方法来接收消息。
 */
public void handleMessage(Message msg) {
}
/**
 * Handle system messages here.这里处理系统的消息。
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

private static void handleCallback(Message message) {
    message.callback.run();
}
从源码可以看出,消息分发处理有三层:
① 当msg.callback !=null,也就是使用了handler的post系列方法发送了消息(将Runnable赋值给了message的callback),消息由handleCallback()方法处理(message.callback.run())
② 当mCallback != null,也就是handler设置了Callback,消息就由handler的Callback的handleMessage()处理
③ 当mCallback为空或Callback的handleMessage()处理完消息表明还有消息要处理,返回false,消息由handler子类的实现方法handleMessage()处理。
    *handler的Callback的源码注释中指出,如果不想实现Handler的子类(必须实现handleMessage()方法处理消息),可以设置CallBack回调接口。

·总结

1. 一个线程中要想创建Handler发送处理消息,要先调用Looper.prepare()和Looper.loop()来创建一个消息队列(MessageQueue)开启一个轮询器与线程关联。

2. 在Looper的两个方法中间创建Handler,handler创建时要拿到与当前线程关联的轮询器(Looper)和轮询器管理的消息队列(MessageQueue)

3. Handler发送消息(Message)其实是发送到了2中的消息队列(MessageQueue),发送消息同时,Handler将自己设置给Message的target

4. 消息是在Looper的loop()方法中循环取出处理,最终由Message的target也就是发送自己的handler处理。


Handler:

创建:在Looper.prepare()和Looper.loop()之间创建

作用:发送消息(Message)到所在线程关联的轮询器(Looper)的消息队列(MessageQueue),并将自己作为target设置给Message

    处理消息,由dispatchMessage()分发给①Callback的handleMessage()、②Handler的handleMessage()或③Handler的handleCallback()处理

Looper 轮询器

创建:由自己的prepare()方法创建并关联当前线程。

作用:Looper.perpare(),创建自己的实例同时创建一个MessageQueue,并将自己设置给当前线程

    Looper.loop()从当前线程拿到Looper及其MessageQueue,循环遍历MessageQueue,取出消息,交给Message的target(发送消息的handler)处理

*Looper.myLooper():获得当前线程所关联的Looper。

MessageQueue 消息队列

创建:Looper的构造方法中创建,最终由Looper的prepare()方法创建

作用:接收handler发送消息时加入进来的消息,将其放入队列中,先入先出

Message 消息

创建:优先用Message.obtain()获取实例,Handler发送消息时创建,最终由MessageQueue管理

作用:携带消息内容传递数据,或作为一个信号(what)

注意:Message在被发送时会将发送它的Handler作为target,在使用Handler的post系列方法时,传入的Runnable对象由Message的callback得到。







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值