05
2017
10

Handle、Message、Looper

Handle、Message、Looper

Handler

对于Handler.sendMessage(Message msg)或者sendEmptyMessageDelayed(int what,long delayMills)来说,其实最终都是调用到了

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

从前面的代码分析,这里的queue就是一个MessageQueue类型的变量,都来自于一个全局变量mQueue。在Handler的构造函数中,如果没有传入Looper的话,默认的mQueue是来自于mLooper之中,而mLooper又是来自Looper .myLooper();

主要的两个构造函数入下:

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

这两个构造函数都是hide的,所以都是通过其余几个构造函数传递到这两个构造函数里来,默认async是false
从上面的代码分析
Looper中的myLooper方法

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

或者是直接调用myQueue方法获取MessageQueue类型获取Looper中的变量mQueue

    public static @NonNull MessageQueue myQueue() {
        return myLooper().mQueue;
    }

而该MessageQueue类型的变量mQueue来自Lopper中的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));
    }


    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

ThreadLocal其实就是一个每个Thread都有的存储空间,如果需要往里面放入数据,则调用其中的set方法

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

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

每个Thread对象中都默认有一个null的threadLocale
ThreadLocal.ThreadLocalMap threadLocals = null;

Looper

looper的静态方法prepare会new一个Looper(同时new一个MessageQueue)并放入每个Thread中所包含的ThreadLocal,相当于每个Thread中都能存储一个Looper
而looper的静态方法loop(),则是会进行一个死循环,一直从该looper中的MessageQueue中来取出首位的msg,并调用
msg.target.dispatchMessage(msg);
而msg.target方法是我们在使用Handler.sendMessage等系列方法时指定的,如最上面的第一段代码,msg.target就是我们调用时指定的Handler,因此looper会首先去调用对应handler的dispatchMessage方法

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

其中msg的callback变量是一个Runnable,如果在创建Message的时候没有指定,则默认为null,如果指定了,则是直接调用该msg.run()

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

若没有,则是调用创建Handler时的构造函数中的Handler.CallBack实现,或者是我们平常使用的new Handler对象

以下总结来自于Android异步消息处理机制

  1. 首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
  2. Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
  3. Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
  4. Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
  5. 在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

那么在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法

如下是大神写的一个关于使用Handler的例子
Android Handler 异步消息处理机制的妙用 创建强大的图片加载类

上一篇:iOS 多任务下载(支持离线 下一篇:GridView布局