Android Framework学习七:Handler、Looper、Message

文章目录

简介

Looper当做一台传送装置,MessageQueue是传送带,传送带上放的是Message,Handler用于发送Message分发与接收处理。

Looper

frameworks/base/core/java/android/app/ActivityThread.java

ActivityThread.main是APP的入口函数,先调用Looper.prepareMainLooper创建Looper,再调用Looper.loop让它跑起来。

java 复制代码
    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

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

        Looper.loop();
    }

frameworks/base/core/java/android/os/Looper.java

java 复制代码
public final class 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;
    ...
}

ThreadLocal 是 Android 和 Java 中一个用于实现线程隔离的工具类,它能让每个使用该变量的线程都拥有独立的副本,线程间对该变量的操作互不影响。

APP入口函数会调用prepareMainLooper->prepare, 会新建一个Looper对象给

sThreadLocal,保证线程有且拥有一个只有自己能用的Looper对象。

sMainLooper通过myLooper函数赋值,其实就是sThreadLocal中的Looper对象

java 复制代码
    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

Looper.loop

loop()其实是在一个死循环中,不断执行loopOnce函数

java 复制代码
    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    @SuppressWarnings("AndroidFrameworkBinderIdentity")
    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("persist.log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        me.mSlowDeliveryDetected = false;

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

在loopOnce中会调用msg.target.dispatchMessage(msg)分发消息

java 复制代码
    private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
            ....
        Message msg = me.mQueue.next(); // might block
        ....
        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);
            }
        }
        ....    
    }

这个msg.target的target其实是Handler对象,msg.target.dispatchMessage调用的是Handler.dispatchMessage

Message

这个target就是Handler, 也就是Message中会有Handler的引用,

frameworks/base/core/java/android/os/Message.java

java 复制代码
    /**
     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
     * members.
     * @param h  The <em>target</em> value to set.
     * @param what  The <em>what</em> value to set.
     * @param obj  The <em>object</em> method to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, Object obj) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.obj = obj;

        return m;
    }

MessageQueue

MessageQueue是由链表组成的,用于存放Message

MessageQueue主要函数

Handler

发送Message时sendMessage最终都会调用enqueueMessage

java 复制代码
    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    /**
     * Enqueue a message into the message queue after all pending messages
     * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     * You will receive it in {@link #handleMessage}, in the thread attached
     * to this handler.
     *
     * @param uptimeMillis The absolute time at which the message should be
     *         delivered, using the
     *         {@link android.os.SystemClock#uptimeMillis} time-base.
     *
     * @return Returns true if the message was successfully placed in to the
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public boolean sendMessageAtTime(@NonNull 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);
    }

会调用queue.enqueueMessage,这个queue其实是MessageQueue,把Message放入MessageQueue

java 复制代码
    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);
    }

接收到消息后处理时

dispatchMessage会调用到handleMessage,就会进入Message的处理部分

frameworks/base/core/java/android/os/Handler.java

java 复制代码
    /**
     * Callback interface you can use when instantiating a Handler to avoid
     * having to implement your own subclass of Handler.
     */
    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) {
    }

    /**
     * Handle system messages here.
     */
    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

Framework学习系列文章

Android Framework学习一:系统框架、启动过程
Android Framework学习二:Activity创建及View绘制流程
Android Framework学习三:zygote
Android Framework学习四:APP速度优化
Android Framework学习五:APP启动过程原理及速度优化
Android Framework学习六:Binder原理
Android Framework学习七:Handler、Looper、Message

作者:帅得不敢出门

相关推荐
androidwork6 分钟前
Kotlin与物联网(IoT):Android Things开发探索
android·物联网·kotlin
橙子199110168 分钟前
在 Kotlin 中,什么是内联函数?有什么作用?
android·开发语言·kotlin
jerry60917 分钟前
LLM笔记(九)KV缓存调研
笔记·深度学习·学习·缓存·transformer
叒卮28 分钟前
小白编程学习之巧解「消失的数字」
数据结构·学习·算法
悠哉清闲35 分钟前
Kotlin 协程 (一)
android·开发语言·kotlin
Y3174291 小时前
Python Day26 学习
python·学习
Cloud Traveler1 小时前
预先学习:构建智能系统的 “未雨绸缪” 之道
人工智能·python·学习
草明1 小时前
使用 adb 命令截取 Android 设备的屏幕截图
android·adb
.生产的驴1 小时前
SpringBoot 商城系统高并发引起的库存超卖库存问题 乐观锁 悲观锁 抢购 商品秒杀 高并发
android·java·数据库·spring boot·后端·spring·maven
N_NAN_N2 小时前
设计模式----软考中级软件设计师(自用学习笔记)
笔记·学习·设计模式