安卓基础组件Looper - 03 java层面的剖析

文章目录

workflow

工作线程 准备Looper

(app主线程中已经准备好了Looper,可以跳过这一节,直接new Handler)

创建Looper,让Looper运行起来。

  • 调用 Looper.prepare() 初始化 Looper

  • 启动轮询器 Looper.loop() 进入循环休眠状态,对queue进行轮询。

    (保证main函数一直运行,一直存活)主线程looper不允许退出。

    • 当消息达到执行时间

      • message queue队列 不为空,取出

      • message queue队列为空,队列阻塞,

    • 等消息队列调用入队 enqueuer Message方法被调用的时候,唤醒队列。从而取出消息停止阻塞。

创建Looper

Activity主线程

app主线程中,可以直接new Handler,跳过这一整章。

prepareMainLooper(),Activity创建时 主线程的Looper是已经准备好了的。

java 复制代码
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    Looper.prepareMainLooper();
    // ...
}

// frameworks/base/core/java/android/os/Looper.java
@Deprecated
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}
其他情况

在app子线程 / framework中的线程中,想要需要自己做两件事:

  • 首先 要创建Looper Looper.prepare

  • 之后 让Looper运行起来Looper.loop()死循环

java 复制代码
// Looper.prepare();  // 子线程
Handler mReportHandler;
mReportHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {}
}
// Looper.loop();     // 子线程

Looper.prepare()

大体流程

Looper.prepare() 首先需要获取当前线程的 Looper

  • 如果有当前线程的Looper,获取该 Looper

  • 如果没有当前线程的Looper,则执行这一步会自动new一个 Looper 并存到线程本地数据区中。

如果涉及创建,则创建Looper过程中的核心内容是:

  • native层
    • 初始化一个 NativeMessageQueue 对象,
      • NativeMessageQueue 继承自MessageQueue
      • 它持有一个Looper指针
    • 初始化 Native 层 Looper 对象
    • 将NativeMessageQueue 对象的地址返回给 Java 层。
  • java层
    • 保存当前线程 Thread 对象。
    • 保存创建的 MessageQueue对象(保存有NativeMessageQueue的地址)
java
申请Looper

从本地线程区获取当前线程的 Looper 对象,没有的话,就初始化一个,并存在线程本地数据区中。

java 复制代码
// frameworks/base/core/java/android/os/Looper.java

public static void prepare() {
    prepare(true);
}

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

// sThreadLocal.get() will return null unless you've called prepare().
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
new Looper

构造函数中:new 一个 Looper 的过程

  • 创建了一个 MessageQueue对象
  • 获取到了当前线程 Thread 对象。
java 复制代码
// frameworks/base/core/java/android/os/Looper.java
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);  //创建MessageQueue对象
    mThread = Thread.currentThread();
}
MessageQueue初始化

MessageQueue 的初始化过程:

java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java
MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    mPtr = nativeInit();	// NativeMessageQueue的地址
    						// 也包含了对epoll的初始化
}
// 调用了 native 方法 nativeInit,对应的 JNI 函数如下
private native static long nativeInit();
native
jni

nativeInit 是一个 Native 方法,对应的 JNI 注册函数如下:

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
static const JNINativeMethod gMessageQueueMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
    { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
    ...
};

static struct {
    jfieldID mPtr;   // native object attached to the DVM MessageQueue
    jmethodID dispatchEvents;
} gMessageQueueClassInfo;


int register_android_os_MessageQueue(JNIEnv* env) {
    int res = RegisterMethodsOrDie(env, "android/os/MessageQueue", gMessageQueueMethods,
                                   NELEM(gMessageQueueMethods));

    jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
    gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");
    gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,
            "dispatchEvents", "(II)I");

    return res;
}
NativeMessageQueue

续上前文,native层这部分的核心内容是

  • 初始化一个 NativeMessageQueue 对象,
    • NativeMessageQueue 继承自MessageQueue
    • 它持有一个Looper指针
  • 初始化 Native 层 Looper 对象
  • 将NativeMessageQueue 对象的地址返回给 Java 层。
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
    if (!nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return 0;
    }

    nativeMessageQueue->incStrong(env);
    return reinterpret_cast<jlong>(nativeMessageQueue);
}

// frameworks/base/core/jni/android_os_MessageQueue.cpp
class NativeMessageQueue : public MessageQueue, public LooperCallback {
private:
    JNIEnv* mPollEnv;
    jobject mPollObj;
    jthrowable mExceptionObj;
};
// frameworks/base/core/jni/android_os_MessageQueue.h
class MessageQueue : public virtual RefBase {
protected:
    sp<Looper> mLooper;
};
cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
// NativeMessageQueue 构造函数
NativeMessageQueue::NativeMessageQueue() :
        mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    // 初始化 Native 层的 looper
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}

Looper.loop()

Looper.loop()在工作线程执行,MSG的消费,执行,都是在执行该函数的线程中,

(这里的工作线程是指,拥有Looper、处理MSG的线程)

大体流程
shell 复制代码
Looper::loop()
    MessageQueue::next
        MessageQueue::nativePollOnce
---jni---
android_os_MessageQueue_nativePollOnce
	NativeMessageQueue::pollOnce
        Looper::pollOnce
        	Looper::pollInner
        		epoll_wait # 进入阻塞

初始化工作完成后,看看 Looper.loop() 方法执行的操作:

核心功能就两点:

  • 获取 TLS 存储的 Looper 对象
  • 进入无限循环,调用 loopOnce 进入休眠状态
java 复制代码
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
    // 获取 TLS 存储的 Looper 对象
    final Looper me = myLooper();
    // 进入无限循环, 
    for (;;) {
        // MessageQueue.next() 获取 Message,可能阻塞
        Message msg = queue.next(); // might block
        // 分发消息,调用 handler 中的回调函数
        msg.target.dispatchMessage(msg); 
    }
}
java
获取Looper

获取 TLS 存储的 Looper 对象很好理解。

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
    // 获取 TLS 存储的 Looper 对象
    final Looper me = myLooper(); 
    me.mInLoop = true;
	//...
}
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}
// sThreadLocal.get() will return null unless you've called prepare().
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
获取msg,处理msg

获取msg、处理 msg 的过程,原先被封装在 loop::loopOnce 中。最终都是调用了MessageQueue.next()

具体,见下一章节。

Looper.loop()
java 复制代码
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
    // 进入无限循环, 
    for (;;) {
        // MessageQueue.next() 获取 Message,可能阻塞
        Message msg = queue.next(); // might block
        // 分发消息,调用 handler 中的回调函数
        msg.target.dispatchMessage(msg); 
    }
}
Looper.loopOnce (已过时)

实际上,Looper.loopOnce是从MessageQueue中取出一个msg并执行。

但在使用中,无限循环内Looper.loopOnce被多次调用。因此,实际上也不需要这个封装了。直接使用 MessageQueue.next()获取msg,和 Handler .dispatchMessage 处理msg。

调用 loopOnce 进入休眠状态

核心流程

  • 通过 MessageQueue 的 next 方法拿到一个 Message,

    这里可能会阻塞休眠

  • 通过 dispatchMessage 调用 Handler 中的回调方法

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
private static boolean loopOnce(final Looper me,
                                final long ident, final int thresholdOverride) {

    // 获取 Message,可能阻塞
    Message msg = me.mQueue.next(); 
    if (msg == null) {}
	// ...
    try {
        //分发消息,调用 handler 中的回调函数
        msg.target.dispatchMessage(msg); 
        if (observer != null) {
            observer.messageDispatched(token, msg); 
        }
        dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
		// ...

    msg.recycleUnchecked();

    return true;
}    
获取msg 休眠

通过 MessageQueue 的 next 方法拿到一个 Message,这里可能会阻塞休眠。

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
    // ...
    // 进入无限循环, 
    for (;;) {
        // MessageQueue.next() 获取 Message,可能阻塞
        Message msg = queue.next(); // might block
        // 分发消息,调用 handler 中的回调函数
        // 但由于阻塞,这里会在 主线程2 唤醒后才调用
        // frameworks/base/core/java/android/os/Handler.java
        // public void dispatchMessage(@NonNull Message msg) {
        msg.target.dispatchMessage(msg); 
    }
}

MessageQueue.next()

调用 nativePollOnce 陷入 Native 层,进入休眠状态,

java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java
Message next() {
    final long ptr = mPtr;	// 这个指向 NativeMessageQueue 还记得吗

    for (;;) {
        // 陷入 Native 层,进入休眠状态
        nativePollOnce(ptr, nextPollTimeoutMillis);

        //......
    }
}

private native void nativePollOnce(long ptr, int timeoutMillis);
native
jni

nativePollOnce 是一个 Native 方法,对应的 JNI 注册函数如下:

cpp 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
static const JNINativeMethod gMessageQueueMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
    // ...
    { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },
    // ...
};
cpp 复制代码
static struct {
    jfieldID mPtr;   // native object attached to the DVM MessageQueue
    jmethodID dispatchEvents;
} gMessageQueueClassInfo;

int register_android_os_MessageQueue(JNIEnv* env) {
    int res = RegisterMethodsOrDie(env, "android/os/MessageQueue", gMessageQueueMethods,
                                   NELEM(gMessageQueueMethods));

    jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");
    gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");
    gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,
            "dispatchEvents", "(II)I");

    return res;
}
native

通过传入的指针,获取到 Native 层的 NativeMessageQueue 对象,接着调用 NativeMessageQueue 对象的 pollOnce 方法。

java 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jlong ptr, jint timeoutMillis) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}

Native 层 Looper 的 pollOnce 函数,pollOnce 内部主要是调用 epoll_wait 来进入休眠状态。

java 复制代码
// frameworks/base/core/jni/android_os_MessageQueue.cpp
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
	// ...
    // 内部调用 epoll_wait 阻塞
    mLooper->pollOnce(timeoutMillis);
	// ...
}

上面已经调用 Native 层 Looper::pollOnce 函数,从而调用 epoll_wait 来进入休眠状态。

cpp 复制代码
// frameworks/core/core/libutils/Looper.cpp
// system/core/libutils/Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    for (;;) {
    	while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            if (ident >= 0) {... return ident;}
        }
        if (result != 0) {return result;}
        // 如果没有 在 Vector<Response> mResponses; 其中有 sp<LooperCallback> callback;
        // 则进入下面的休眠状态
        result = pollInner(timeoutMillis);
    }
}
cpp 复制代码
// system/core/libutils/Looper.cpp
int Looper::pollInner(int timeoutMillis) {
    // ...
    int eventCount = epoll_wait(epollfd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

pollOnce 的具体代码分析可以参考上述Looper - native - pollAll 部分,这里不再重复。

至此,我们的线程就下 cpu,进入休眠状态。

其它线程 发送msg

大体来说

初始化一个 Handler 对象,再传入 msg。发送消息大致三步:

  • 初始化一个 Handler 对象,覆写 Handler 的 handleMessage 方法
  • 构建一个 Message 对象
  • 通过 Handler 的 sendMessage 方法发送消息

后续,会执行 handleMessage

准备Handler

在使用 Looper 的线程中通常会初始化一个 Handler 对象,重写其handleMessage方法。

构造函数

Handler时,需要指定 Looper 意味着于此同时确定了对应的MessageQueue。

java 复制代码
// frameworks/base/core/java/android/os/Handler.java
    public Handler(@NonNull Looper looper) {
        this(looper, null, false);
    }
    public Handler(@NonNull Looper looper, @Nullable Callback callback) {
        this(looper, callback, false);
    }

    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async,
            boolean shared) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
        mIsShared = shared;
    }
重写 handleMessage

Handler.sendMessage 方法调用时,(无论是本线程的Handler还是其它线程的Handler),在MessageQueue中排队后都会调用该HandelerhandleMessage方法。

java 复制代码
// new 一个 Handler,覆写 handleMessage 方法
mHandler = new Handler() {  
    public void handleMessage(Message msg) {
        //定义消息处理逻辑. 
    }
};
java 复制代码
// 典型的关于Handler/Looper的线程
class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();   // 子线程需要,主线程不需要
        mHandler = new Handler() {  
            public void handleMessage(Message msg) {
                //定义消息处理逻辑. 
                Message msg = Message.obtain();
            }
        };
        Looper.loop();   // 子线程需要,主线程不需要
    }
}
重要的成员变量

Handler 初始化过程中,要对 Handler 中有两个重要变量进行赋值:

  • mLooper:当前线程的 Looper
  • mQueue: 当前进程的 MessageQueue
java 复制代码
public Handler() {
    this(null, false);
}

public Handler(@Nullable Callback callback, boolean async) {
    // 当前线程的 Looper 对象
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread " + Thread.currentThread()
            + " that has not called Looper.prepare()");
    }
    // 当前进程的 MessageQueue 
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

Handler发送Msg

准备Msg

做好以上的准备工作后,准备Message

java 复制代码
// 构建一个 Message
Message msg = new Message();
// 获知遵循享元模式:
Message msg = Message.obtain();
msg.what = 2; 
msg.obj = "B"; 

Message msg = mReportHandler.obtainMessage(MSG_SWITCH_TO_SDR_MEMC);
mReportHandler.sendMessage(message);

// 通过 Handler 的 sendMessage 方法发送消息
mHandler.sendMessage(msg);

我们先看看 Message 的初始化过程:

java 复制代码
// frameworks/base/core/java/android/os/Message.java
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();
}

从缓存 sPool 里面取 Message,如果没有的话就 new 一个 Message。

Handelr发送msg
主要函数

子线程 Handler为了发送MSG,归根结底,都是使用了 入队MSG Handler.enqueueMessage()

Handler::sendMessage

mHandler.sendMessage(msg) 内部继续对传入的 Message 进行进一步赋值。例如:把handler的this指针,赋值给了 msg 的 target 成员,这样调用时就知道应该执行哪一个Handler对应的函数了

java 复制代码
// frameworks/base/core/java/android/os/Handler.java
public final boolean sendMessage(@NonNull Message msg) { ... }
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) {
    // 注意这里
    msg.target = this;  // 把handler的this指针,赋值给了msg的 target 成员
    msg.workSourceUid = ThreadLocalWorkSource.getUid();
	// 最终调用到 MessageQueue 的 enqueueMessage 方法
    return queue.enqueueMessage(msg, uptimeMillis);
}
MessageQueue::enqueueMessage

MessageQueue.enqueueMessage 代码有点长,核心逻辑:

  • 把 Message 插入 mMessages 链表
  • 调用 native 方法 nativeWake 唤醒 native 层的 epoll
java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java
boolean enqueueMessage(Message msg, long when) {
	// 添加msg到链表
	Message p = mMessages;
    msg.next = p;
    mMessages = msg;

    // We can assume mPtr != 0 because mQuitting is false.
    // 唤醒Looper,进入native
    if (needWake) {
        nativeWake(mPtr);
    }
nativeWake

nativeWake 最终会调用 native 层 mLooper 的 wake 函数,

java 复制代码
private native static void nativeWake(long ptr);

向 eventfd 写入数据,唤醒与 eventfd 绑定的 epoll。

cpp 复制代码
// nativeWake 对应的 JNI 函数 
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->wake();
}

void NativeMessageQueue::wake() {
    mLooper->wake();
}

// eventfd 写数据,唤醒 epoll
void Looper::wake() {
    // 大体就是
    write(mWakeEventFd.get(), &inc, sizeof(uint64_t));
}
java 复制代码
// 这个mWakeEventFd就是epoll关注的句柄之一
void Looper::rebuildEpollLocked() {
    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event));
    eventItem.data.fd = mWakeEventFd.get();
cpp 复制代码
// 之前陷入阻塞,也是和eventItems有关
int Looper::pollInner(int timeoutMillis) {
    // ...
    epoll_wait(epollfd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);

接下来我们就来看看 epoll 唤醒以后的流程。

(仅作了解) 工作线程中执行

以下仅作了解,一般来说使用时不需要关心。

之前我们 或被动,或主动的在一个/一些线程中调用了 Looper::loop()

在线程(一般是主线程)中执行Looper.loop(),则这个线程就是"工作线程"。可以认为是MSG的消费者:所有的MSG的消费,执行都是在该线程中,

  • 调用了 Looper::loop() 的线程,会从进程的MessageQueue中取出、处理MSG,并执行Hanlder的重载。

  • 因为 MessageQueue 是线程安全的,所以可以有多个线程调用 Looper::loop(),这些线程并行的处理Hanlder。

唤醒

native

Looper::pollInner 解除阻塞后,一路上函数调用栈恢复。相对应的,Java 层的 next 方法被唤醒。

shell 复制代码
Looper::loop()
    MessageQueue::next
        MessageQueue::nativePollOnce
---jni---
android_os_MessageQueue_nativePollOnce
	NativeMessageQueue::pollOnce
        Looper::pollOnce
        	Looper::pollInner
        		epoll_wait # 解除阻塞
java

唤醒后,一般的流程就是从 mMessages 中找个合适的 message 返回,

MessageQueue::next()
java 复制代码
// frameworks/base/core/java/android/os/MessageQueue.java
public final class MessageQueue {
Message next() {
	// ...
    for (;;) {
		// 在这个位置陷入 Native 层,进入休眠状态
        // 所以也是从这个位置唤醒
        nativePollOnce(ptr, nextPollTimeoutMillis);
        // 从 mMessages 链表中选取一个合适的 message 返回
        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
Looper::loop

再继续返回后进入上一层

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
    // 进入无限循环, 
    for (;;) {
        // 从这里恢复阻塞
        Message msg = queue.next(); // MessageQueue.next() 获取 Message
        // 分发消息,调用 handler 中的回调函数
        msg.target.dispatchMessage(msg); 
    }
}

代码很多,核心的流程只有两点:

  • next() 处返回一个合适的 message
  • 通过 msg.target.dispatchMessage(msg) 调用 handler 中的回调

至此,整个 Looper 流程就走完了。

唤醒后

shell 复制代码
Looper.loop() # 唤醒后执行如下步骤
	MessageQueue.next()			# 获取msg
	Handler.dispatchMessage 	# 处理msg
		Handler.handleMessage
获取MSG

Looper不断的调用,从消息队列中获取消息使用for循环

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
*/
public static void loop() {
    final Looper me = myLooper();

    for (;;) {
        // MessageQueue.next() 获取 Message,可能阻塞
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
        // 处理MSG,下文会介绍
处理MSG

主线程处理,之前传入MessageQueue的MSG,在主线程中执行。

java 复制代码
// frameworks/base/core/java/android/os/Looper.java
public static void loop() {
	// ...
        // 由于阻塞,在 主线程唤醒后 开始处理获得的msg
    	// 分发消息,调用 handler 中的回调函数
        msg.target.dispatchMessage(msg); 
    }
}

Message持有Handler,Handler持有Callback。

java 复制代码
// frameworks/base/core/java/android/os/Message.java
public final class Message implements Parcelable {
    @UnsupportedAppUsage
    // 这个msg.target就是Handler的this指针,是其他线程初始化Msg时自动填入
    /*package*/ Handler target;
java 复制代码
// frameworks/base/core/java/android/os/Handler.java
public class Handler {
    public void handleMessage(@NonNull Message msg) {}
    final Callback mCallback;
    public interface Callback {
        boolean handleMessage(@NonNull Message msg);
    }
}
Handler::dispatchMessage

Handler的方法 handleMessage dispatchMessage 等,最终会调用到以下方法

java 复制代码
// frameworks/base/core/java/android/os/Handler.java
/**
 * Handle system messages here.
 */
public void dispatchMessage(@NonNull Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);	// 1 Runnable run
    } else {
        if (mCallback != null) { // 2 final Callback mCallback;
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

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

public Handler(@Nullable Callback callback, boolean async) {
    mLooper = Looper.myLooper();
    mQueue = mLooper.mQueue;
    mCallback = callback;		// 2 执行这里的 handleMessage
}
public void handleMessage(@NonNull Message msg) { // 3 执行子类的重载(通常说的就是这里)
}
Handler::handleMessage

这也是初始化 Handler时,需要重写 handleMessage 的原因

在使用 Looper 的线程中通常会初始化一个 Handler 对象:

java 复制代码
// new 一个 Handler,覆写 handleMessage 方法
mHandler = new Handler() {  
    public void handleMessage(Message msg) {
        //定义消息处理逻辑. 
    }
};
相关推荐
源码姑娘18 分钟前
基于SpringBoot的校园二手交易平台(源码+论文+部署教程)
java·spring boot·后端·毕业设计
剑走偏锋o.O21 分钟前
基于 Vue 和 SSM 的前后端分离项目实战:登录与注册功能实现
java·vue.js·框架·ssm
非 白24 分钟前
【Java 后端】Restful API 接口
java·开发语言·restful
rider18924 分钟前
Java多线程及线程变量学习:从熟悉到实战(下)
java·开发语言·学习
元亓亓亓25 分钟前
java后端开发day26--常用API(一)
java·开发语言
JP-Destiny26 分钟前
后端-Java虚拟机
java·开发语言·jvm
Crime_man28 分钟前
一次有趣的前后端跨越排查
java·前端·vue.js·spring
m0_5485030329 分钟前
基于Springboot高校社团管理系统【附源码+文档】
java·spring boot·后端
lzz的编码时刻29 分钟前
Spring Security简介与使用
java·后端·spring
葡萄_成熟时_32 分钟前
JavaWeb后端基础(4)
java·开发语言·数据库·maven·web