【Android学习】Looper/Handler/Message源码学习1

简单说一下

有好一阵子(估计有大半年)没记笔记了,工作原因,很多挺想说的,后面有机会单独记录吧。工作时间比较长,做过很多东西,但是没有系统的记录和梳理,有时候一回想或者面试(面试别人或者被别人面),发现脑子一片空白。把项目做出来可能不会有什么挑战,但是条理清晰、层次分明的剖析里面涉及的技术点,真的就只能点到为止了,很多东西知道概念或者基本能理解概念,但是想讲清楚,就困难了。后面奔着这个目标,把学习过程中我认为比较重要或者比较有意思的部分都记录一下,不管是java语言,还是安卓,还是其他技术,帮助自己理解的更深刻一些。同时也要加强动手,很多技术,只有上手摸了,才能真正理解。鉴于此,我喜欢的CTF刷题,只能优先级放低(虽然也大半年没刷了),先把JAVA和安卓系统的学一遍,其它的慢慢来。

观点

Looper/Handler/Message是安卓上常用的消息通信机制,使用非常方便。从命名上就能看出三者的功能定位:Looper负责消息循环,Handler负责消息处理,Message是消息定义。从这个角度推理看,核心是Looper和Message,因为这个是通用方案,所以Handler更多的会做一些分发上的处理,而不会有太复杂的逻辑。

Handler

先从简单的看起,看下Handler的变量定义:

    @UnsupportedAppUsage
    final Looper mLooper;
    final MessageQueue mQueue;
    @UnsupportedAppUsage
    final Callback mCallback;
    final boolean mAsynchronous;
    @UnsupportedAppUsage
    IMessenger mMessenger;

再看下构造函数:

public Handler(@NonNull Looper looper)
public Handler(@NonNull Looper looper, @Nullable Callback callback)
public Handler(boolean async)
public Handler(@Nullable Callback callback, boolean async)
Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async)

	public Handler(@Nullable 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 " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    @UnsupportedAppUsage
    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

其中,looper是必须的,即使不通过参数定义,也会通过Looper.myLooper获取到, mQueue直接取的是Looper的值,双方共用一个MessageQueue。

消息分发函数如下:

	public interface Callback {
        /**
         * @param msg A {@link android.os.Message Message} object
         * @return True if no further handling is desired
         */
        boolean handleMessage(@NonNull Message msg);
    }
    
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(@NonNull Message msg) {
    }
	public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

处理逻辑很简单:优先使用msg自带的callback进行消息处理,否则使用Handler中被设置的callback,
如果这两个callback都为null,就使用Handler定义的handleMessage方法,一般由子类覆写。
其他的大部分是快捷方法:
obtainMessage:创建新的Message实例。(Handler本身也作为参数传入)
post/postAtTime/sendMessage等等,都是发送消息,最终都会调到下面这个函数:

	private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

queue就是前面变量定义的mQueue,虽然目前还不清楚MessageQueue的定义,但是从这也可以推出Looper应该是通过MessageQueue进行消息循环的,机制是通过Handler的post/send等方法进行让消息入队列,Looper通过循环机制取出分发,稍后再结合源码看。
ok,到这里,前面的主要变量,除了mMessener(暂时不聊),就剩下mAsynchronous,这个值只在enqueueMessage的时候,用于设置msg的属性的。

还有少数几个不常用的函数:

	public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }

        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }

        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }

不知道为啥叫这个名字,其实是同步执行的一个策略,如果当前就是handler的looper线程,就直接执行,否则的话使用BlockingRunnable封装执行,BlockingRunnable是内部类,会等待直至msg被执行完毕。该方法的注释说明是不建议使用,有死锁或者其它问题,确实,不建议。

	public final boolean executeOrSendMessage(@NonNull Message msg) {
        if (mLooper == Looper.myLooper()) {
            dispatchMessage(msg);
            return true;
        }
        return sendMessage(msg);
    }

不多说,逻辑很简单。

Message

Message的常用字段如what、arg1、arg2这些都是用于数据传输的,看下其它变量:

    @UnsupportedAppUsage
    /*package*/ Handler target;
    @UnsupportedAppUsage
    /*package*/ Runnable callback;
    // sometimes we store linked lists of these things
    @UnsupportedAppUsage
    /*package*/ Message next;
    /** @hide */
    public static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 50;

target指该Message指定的处理对象,callback是指负责实际执行的方法。而next则说明使用的是链表结构,静态变量sPool则说明整个进程共享一个Message链表。

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

obtain是获取Message的静态方法,逻辑很简单,优先从链表取, 如果没有链表,则返回一个新对象。可以看出sPool是废弃Message的表头,如果表头不为空,则直接返回表头,并将新表头设为原表头的next,同时将原表头的next置空。sPoolSize用于计算链表大小,用于控制内存占用。
既然使用废弃Message链表,那就有生成的地方,那就是recycleUnchecked函数:

    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }
	@UnsupportedAppUsage
    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 = UID_NONE;
        workSourceUid = UID_NONE;
        when = 0;
        target = null;
        callback = null;
        data = null;

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

recycleUnchecked前面一堆都是数据清理,后面几行就是将本Message设为新表头,并将next设为原表头,更新计数。从obtain和recycle函数来看,使用链表来缓存废弃Message真是方便实用。
其他函数都是些简单的静态方法,略过不表。不过源码看到这里,相信有的同学一定有跟我一样的疑问,既然Message有next,那MessageQueue是个什么形态?先看Looper,结合Looper食用更佳。

Looper

从前面的分析可以看出Looper主要用于消息循环。

	// sThreadLocal.get() will return null unless you've called prepare().
    @UnsupportedAppUsage
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    @UnsupportedAppUsage
    private static Looper sMainLooper;  // guarded by Looper.class
    private static Observer sObserver;
    @UnsupportedAppUsage
    final MessageQueue mQueue;
    final Thread mThread;
    private boolean mInLoop;
    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();
    }

基本上,讲解Looper使用的书籍,都要强调使用Looper必须先调用prepare,确实,从上面两个函数可以看出,Looper是跟线程绑定的,一个线程有且只有一个Looper,通过ThreadLocal变量来控制。其他变量:sObserver从名称基本就可以确定是观察者,观察消息分发相关的事情;sMainLooper,静态变量,对应进程的主线程Looper,一个进程一个。

	public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        if (me.mInLoop) {
            Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }
        me.mInLoop = true;
        // 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();
        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        me.mSlowDeliveryDetected = false;

        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }

loop函数,前面是一些状态判断,关键的循环在后面几行,通过loopOnce进行消息获取和分发。

	private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
      1)Message msg = me.mQueue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return false;
        }

        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " "
                    + msg.callback + ": " + msg.what);
        }
        // Make sure the observer won't change while processing a transaction.
        final Observer observer = sObserver;

        final long traceTag = me.mTraceTag;
        long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
        long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
        if (thresholdOverride > 0) {
            slowDispatchThresholdMs = thresholdOverride;
            slowDeliveryThresholdMs = thresholdOverride;
        }
        final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
        final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

        final boolean needStartTime = logSlowDelivery || logSlowDispatch;
        final boolean needEndTime = logSlowDispatch;

        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }

        final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
        final long dispatchEnd;
        Object token = null;
        if (observer != null) {
            token = observer.messageDispatchStarting();
        }
        long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
        try {
           2)msg.target.dispatchMessage(msg);
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } catch (Exception exception) {
            if (observer != null) {
                observer.dispatchingThrewException(token, msg, exception);
            }
            throw exception;
        } finally {
            ThreadLocalWorkSource.restore(origWorkSource);
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        if (logSlowDelivery) {
            if (me.mSlowDeliveryDetected) {
                if ((dispatchStart - msg.when) <= 10) {
                    Slog.w(TAG, "Drained");
                    me.mSlowDeliveryDetected = false;
                }
            } else {
                if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                        msg)) {
                    // Once we write a slow delivery log, suppress until the queue drains.
                    me.mSlowDeliveryDetected = true;
                }
            }
        }
        if (logSlowDispatch) {
            showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", 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);
        }

      3)msg.recycleUnchecked();

        return true;
    }

这个函数看似很长,中间大段代码都是辅助功能,关键流程就是标注数字的3行

1)Message msg = me.mQueue.next(); 

用来取消息

2)msg.target.dispatchMessage(msg);

用来进行消息分发处理,由对应的Handler的dispathMessage方法出来该消息

3)msg.recycleUnchecked();

消息处理完毕后,进行回收处理。

从这个处理链条来看,Looper就是个引擎,用for循环来当发动机进行消息驱动,是个典型的消息获取、分发逻辑,而链条则是MessageQueue,Handler中使用enqueueMessage进行消息入队,Looper使用next获取消息出队,下面我们就从这两个方法入手来分析。
oops,文章超长,另开一篇继续。

你可能感兴趣的:(android,android,学习)