Android Looper用法及分析

先看一下源码中对looper进行的解释,
Android Looper用法及分析_第1张图片
根据注释内容,可以了解到,消息循环的交互情况都是通过handler进行的。
再不和handler搭配的情况下,通常都是以looper.prepare和looper.loop这种方式成对出现的,使在这两句话中间执行的内容都是通过looper进行通信执行相应内容。

此类还有对api实施进行注释描述,贴上来也一起看一下吧。
Android Looper用法及分析_第2张图片
这部分描述可以看到,looper基于MessageQueue并可以影响任务队列的状态。通常都是在MessageQueue或者Handler上进行定义,这里讲了looper的作用和其定义的时机。

个人理解:
looper通常都是在非主线程的时候使用让部分代码块可以作用在主线程,进行ui更新等一些操作。用到的地方有很多,在activityThread当中可以看到很多looper的影子。在什么时候用源码的注释上面解释的挺清晰了。
该类中中在跨进程部分运用的都是binder进行通信,threadlocal进行线程管理。

此类中不对外暴露的方法不进行介绍。
----------------------------------------------------------我是分割线----------------------------------------------------------

方法介绍

prepare()方法最终会传递true到 prepare(boolean quitAllowed)方法当中,这里直接看 prepare(boolean quitAllowed)方法。
Android Looper用法及分析_第3张图片
这里可以看到该方法会优先判断threadlocal线程池里面是否为null,里面有数据的时候就会抛出运行异常(因为代表这个时候looper有正在运行,必须要保持一个looper),里面没有数据的话就会把传递过来的boolean类型放到looper对象的参数中,然后设置到线程池里去运用。

getMainLooper方法,会锁住looper类,然后返回当前正在使用的looper。

myLooper()方法,会从当前的threadlocal获取内容并进行返回。

showSlowLog(long threshold, long measureStart, long measureEnd,String what, Message msg)方法,传递过来的参数如果还在倒计时,那么就打印log并返回为true,打印的log内容见下图:在这里插入图片描述

myLooper()方法,会获取当前threadllocal里面的内容进行return。

myQueue()方法,执行mylooper方法获取其mQueue变量进行retun。

Looper(boolean quitAllowed)方法,实例化的时候会把传递过来参数作为实例化MessageQueue的参数,并且当前的线程会获取当前的线程,表述的可能不太清晰看图吧:
Android Looper用法及分析_第4张图片

isCurrentThread()方法,该方法会判断looper当前的sThread常量和Thread.currentThread()返回的变量是否相等(==)

setMessageLogging(@Nullable Printer printer)方法,会把传递过来的Printer 赋值给当前looper的mLogging变量。Printer 的用法还请再看相关介绍~

quit()方法,执行looper当前queue的quit(blooean)方法,传递false过去。

quitSafely()方法,同样执行queue的quit方法,但是会传递true过去,至于这个方法传递不同参数的含义请到queue分析当中去看。

getThread()方法,return looper当前的mThread。

getQueue()方法,return looper当前的mQueue。

dump(@NonNull Printer pw, @NonNull String prefix) 方法,会用传递过来的pw打印出prefix内容,然后执行mqueue.dump方法,该方法第三个参数为null。

dump(@NonNull Printer pw, @NonNull String prefix, Handler handler)方法,会用传递过来的pw打印出prefix内容,然后执行mqueue.dump方法,该方法第三个参数为传递过来的handler。具体执行内容也请看queue里面的dump方法。(该方法为hide,写多了)

toString()方法,这个就看图片吧。
在这里插入图片描述

prepareMainLooper()方法,会把false传递到要执行的prepare方法中。然后synchronized-- looper类 判断当前的looper是否为null,为null的话就走myLooper方法进行获取,不为null则会抛出IllegalStateException。

loop方法内容比较多,也需要结合代码进行查看。先进行大概描述,然后再结合图片里面的代码进行查看。
looper.loop会先执行myLooper方法获取looper判断是否为null。获取当前looper的mQueue,进入到无限循环当中,获取queue里面的message。如果message为null就return,不为null时就会获取当前的observer,获取当前message里面的相关时间和tag用来判断message的执行时间。把相关tag放到trace.tracebegin当中进行跟踪。判断当前observer是否为空不为空的话执行相应方法,首先执行messageDispatchStarting方法,在message.target执行dispatchMessage之后执行observer.messageDispatched方法,如果这个时候走到catch里面了,会执行observer的dispatchingThrewException方法。trycatch最终都会跟踪该消息。判断时间打印出相应的log,最终会执行message.recycleUnchecked()重置message 的内容和Binder.clearCallingIdentity()方法清理标识。

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

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

        boolean slowDeliveryDetected = false;

        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
            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 {
                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 (slowDeliveryDetected) {
                    if ((dispatchStart - msg.when) <= 10) {
                        Slog.w(TAG, "Drained");
                        slowDeliveryDetected = false;
                    }
                } else {
                    if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                            msg)) {
                        // Once we write a slow delivery log, suppress until the queue drains.
                        slowDeliveryDetected = 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);
            }

            msg.recycleUnchecked();
        }
    }

至此looper对外暴露的方法基本都已经写出。

你可能感兴趣的:(android,ui,binder)