欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handle、Message、Looper

程序员文章站 2022-07-14 15:10:00
...

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 异步消息处理机制的妙用 创建强大的图片加载类

相关标签: handler机制