Tags : zaze android

[TOC]


Android消息机制篇

参考资料

以上部分图片和解读说明摘自以下参考资料。

« Android的设计和实现:卷I» «深入理解Android: 卷I»

0. 消息驱动机制

Android 扩展了线程的退出机制,在启动线程时,在线程内部创建一个消息队列, 然后让线程进入无限循环; 在这个无限循环中,线程会不断的检查消息队列中是否是消息。如果需要执行某个任务,就向线程的消息队列中发送消息,循环检测到有消息到来 便会获取这个消息 进而执行它。如果没有则线程进入等待状态。

0.1 一图而窥之

作者太懒, 还在描边中~~

1. 浅见Java层

  • Looper调用prepare(),在当前执行的线程中生成仅且一个Looper实例,这个实例包含一个MessageQueue对象
  • 调用loop()方法,在当前线程进行无限循环,不断从MessageQueue中读取Handler发来的消息。
  • 生成Handler实例同时获取到当前线程的Looper对象
  • sendMessage方法, 将自身赋值给msg.target, 并将消息放入MessageQueue中
  • 回调创建这个消息的handler中的dispathMessage方法,
/**
 * 构建自己Looper线程,体验消息驱动。(可以直接使用Android 提供的HandlerThread)
 * Looper 线程的特点就是 run方法执行完成之后不会推出 而是进入一个loop消息循环。
 */
class LooperThread extends Thread {
    public Handler mHandler;
    
    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // 处理消息
            }
        };
        Looper.loop();
    }
}
/**
 * 穿插一下ThreadLocal(线程局部变量)
 * 实质是线程的变量值的一个副本
 * 而他存取的数据,就是的当前线程的数据
 */
public class ThreadLocal<T> {
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
}

1.1 消息(Message)

了解一下Parcelable和Serializable序列化接口, 号称快10倍, 不过使用相对复杂。

public final class Message implements Parcelable {
    /*消息码, 区分消息类型*/
    public int what;
    ...
    // 表示什么时候执行
    /*package*/ long when;
    ...
    // 存储了下一条消息的引用
    /*package*/ Message next; 
    private static final Object sPoolSync = new Object();
    // 消息池
    private static Message sPool;
    // 消息池当前大小
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 10;
    
    /**
     * 获取消息的通用方法
     */
    public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                // 指向消息的头部
                Message m = sPool;
                // 将消息池头部指向下一条
                sPool = m.next;
                m.next = null;
                // 消息池大小减1
                sPoolSize--;
                // 返回从消息池中取得的消息
                return m;
            }
        }
        // 消息池为空就创建一个消息
        return new Message();
    }
    
    // 实现Parcelable接口的方法, 可以将写入Parcel的对象还原为Message
    public static final Parcelable.Creator<Message> CREATOR  = new Parcelable.Creator<Message>() {
        public Message createFromParcel(Parcel source) {
            Message msg = Message.obtain();
            msg.readFromParcel(source);
            return msg;
        }
        
        public Message[] newArray(int size) {
            return new Message[size];
        }
    };
    
    /**
     * 此处完成了消息池的初始化
     * 使用消息的一方(),只要调用了recycle方法便把会废弃的消息放入消息池中以便重新利用。
     * 放入时这个消息的数据将被清空, 若要使用消息池中的消息, 需要调用obtain方法重新初始化
     */
    public void recycle() {
        clearForRecycle();
        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
    }
    
    /*package*/ void clearForRecycle() {
        flags = 0;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        when = 0;
        target = null;
        callback = null;
        data = null;
    }
    
}

1.2 消息循环(Looper)

  • prepare()与当前线程绑定。
  • loop()方法,循环调用MessageQueue.next()获取消息(消息驱动),交给Message.target.dispatchMessage分发处理(target指Handler, 在Handler.enqueueMessage中被赋值)。
public class Looper {
    // 定义一个线程局部对象存储Looper对象
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    final MessageQueue mQueue;
    final Thread mThread;
    
    /**
     * 创建了MessageQueue对象
     * 建立了MessageQueue和NativeMessageQueue的关系
     * 初始化了Native层的Looper
     * 持有当前线程的引用
     */
    private Looper() {
        // 创建了MessageQueue对象
        mQueue = new MessageQueue();
        // 将当前线程状态标记为run
        mRun = true;
        // 存储当前线程
        mThread = Thread.currentThread();
    }
    
    /**
     *  prepare()只能被调用一次, 否则直接抛出异常
     *  Looper对象存入ThreadLocal ,保证一个线程中只有一个Looper
     */
    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));
    }
    
    /**
     * loop 必须在prepare()后执行,否则报错
     */
    public static void loop() {
        Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        MessageQueue queue = me.mQueue;
        // 在IPCThreadState中记录当前线程所属的PID 和 UID
        // 了解一下Binder
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        while (true) { 
            // 循环监听获取消息, 可能阻塞
            Message msg = queue.next();
            if (msg != null) {
                if (msg.target == null) {
                    return;
                }
                ......
                // 将获取到的消息交给消息处理器
                msg.target.dispatchMessage(msg);
                ......
                // 将处理过的消息回收并放入到消息池中
                msg.recycle();
            }
        }
    }
}

1.3 消息队列(MessageQueue)

java层实例化对象时, 同时native层也完成初始化(NativeMessageQueue) 保持了一个按照执行时间排序的消息队列,提供了对消息队列管理的一些api

image_1c9odn8dlocl1lnh18mkahqbdo9.png-85.5kB

  • postSyncBarrier() 同步屏障

同步屏障

Android 中的 Message 可以分了 同步消息和异步消息 平时这两种消息没有什么区别, 只有当设置了 同步屏障时才有差异 当设置了同步屏障时, 将会过滤这个同步屏障消息之后执行的所有的同步消息 所以同步屏障相当于一个过滤器,当有需要优先处理的消息时可以设置同步屏障

private int postSyncBarrier(long when) {
    // 插入一条同步屏障消息
    synchronized (this) {
        final int token = mNextBarrierToken++;
        final Message msg = Message.obtain();
        msg.markInUse();
        msg.when = when;
        msg.arg1 = token;

        Message prev = null;
        Message p = mMessages;
        if (when != 0) {
            while (p != null && p.when <= when) {
                prev = p;
                p = p.next;
            }
        }
        if (prev != null) {
            msg.next = p;
            prev.next = msg;
        } else {
            msg.next = p;
            mMessages = msg;
        }
        return token;
    }
}
  • 构造函数
// 按照执行时间排序的消息队列
Message mMessages;
public class MessageQueue {
    boolean mQuitAllowed = true; // 默认允许推出, 没看到置为false的地方
    private int mPtr; // used by native code

    private native void nativeInit();
    
    MessageQueue() {
        // 执行Native层初始化操作
        nativeInit();
    }
    
}
  • MessageQueue.enqueueMessage()
final boolean enqueueMessage(Message msg, long when) {
    // 判断消息是否被使用, 新消息一定是未使用, 在next()里面被处理的消息将被标记为FLAG_IN_USE
    if (msg.isInUse()) {
        throw new AndroidRuntimeException(msg + " This message is already in use.");
    }
    // mQuitAllowed默认为true, 没找到设置为false的地方
    if (msg.target == null && !mQuitAllowed) {
        throw new RuntimeException("Main thread not allowed to quit");
    }
    final boolean needWake;
    synchronized (this) {
        if (mQuiting) { // 默认false, 当target(Handler) 所在线程异常退出时置为true
            RuntimeException e = new RuntimeException(
                msg.target + " sending message to a Handler on a dead thread");
            return false;
        } else if (msg.target == null) {
            mQuiting = true;
        }
        // 给新入队消息赋值执行时间
        msg.when = when;
        // 取出消息队列头部
        Message p = mMessages;
        // 对应三种情况(此时需要将新消息插入头部)
        // 1)消息队列为空 
        // 2)新入队消息需要立即执行 
        // 3)新入队消息的执行时间早于消息队列头部消息的执行时间
        if (p == null || when == 0 || when < p.when) {
            msg.next = p;
            mMessages = msg;
            // 有新消息要处理 若之前是阻塞状态则需要唤醒
            needWake = mBlocked;
        } else {
            // 遍历根据执行时间插入到指定位置
            Message prev = null;
            while (p != null && p.when <= when) {
                prev = p;
                p = p.next;
            }
            msg.next = prev.next;
            prev.next = msg;
            // 头部消息没有发生变化 不需要唤醒
            needWake = false;
        }
    }
    if (needWake) {
        // 唤醒
        nativeWake(mPtr);
    }
    return true;
}
  • MessageQueue.next() — 源码更新为8.1版本
 Message next() {
    //如果消息循环已经退出并被处理,返回。
    //如果应用程序尝试在退出后重新启动looper,就会发生这种情况。
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }
    int pendingIdleHandlerCount = -1; // IdleHander的数量, 下面有介绍IdleHandler
    int nextPollTimeoutMillis = 0; // 空闲等待时间
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
        // 传入NativeMessageQueue的地址, 和等待时间
        nativePollOnce(ptr, nextPollTimeoutMillis);
        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            if (msg != null && msg.target == null) {
                // msg.target == null 表示碰到了同步屏障
                // 遍历消息队列直到找到异步消息 或者 直到最后都没有找到
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                // 当前时间大于消息执行时间,消息队列指向下一条, 将执行的消息标记使用并返回
                if (now < msg.when) {
                    // 未到消息执行时间, 计算到可以执行的时间的时间差
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // 标记为不阻塞
                    mBlocked = false;
                    //  移除消息队列头
                    if (prevMsg != null) {
                        // 碰到过同步屏障
                        // prevMsg表示最后一条同步消息
                        // prevMsg.next()等同于mMessages
                        prevMsg.next = msg.next;
                    } else {
                        // 没有碰到同步屏障是为null
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    // 消息标记为已使用
                    msg.markInUse();
                    return msg;
                }
            } else {
                nextPollTimeoutMillis = -1;
            }
            if (mQuitting) {
                dispose();
                return null;
            }
            // 当前时间空闲, 看看有没有IdleHandler需要执行, 若没有则将当前线程状态设置为阻塞
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                mBlocked = true;
                continue;
            }
            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        }
        // 处理空闲消息
        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            mPendingIdleHandlers[i] = null; // release the reference to the handler
            boolean keep = false;
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }
            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }
        pendingIdleHandlerCount = 0;
        nextPollTimeoutMillis = 0;
    }
}

1.4 消息处理器(Handler)

Handle是Looper线程的消息处理器, 承担了发送消息和处理消息两部分工作。

  • 构造函数
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
IMessenger mMessenger; // 用于跨进程发送消息
public Handler() {
    ....
    // 将 Looper、MessageQueue和Handler关联到一起
    mLooper = Looper.myLooper();4
    if (mLooper == null) {
    // 必须调用Looper.prepare()后才能使用
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = null;
}
  • Handler.post(new Runnable())

实际是发送了一条消息,此处的Runnable并没有创建线程,只是作为一个callback使用

public final boolean post(Runnable r){
   return  sendMessageDelayed(getPostMessage(r), 0);
}

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}
  • Handler.sendMessageAtTime()

将自身赋值给msg.target, 并将消息放入MessageQueue中

/**
 * uptimeMillis 表示何时处理这个消息
 */
public boolean sendMessageAtTime(Message msg, long uptimeMillis){
    boolean sent = false;
    MessageQueue queue = mQueue;
    if (queue != null) {
        // 将当前的Handler 指定为处理消息的目标端
        msg.target = this;
        // 入队
        sent = queue.enqueueMessage(msg, uptimeMillis);
    }
    else {
        RuntimeException e = new RuntimeException(
            this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
    }
    return sent;
}
  • Handler.dispatchMessage()消息分配

以下源码可以看出, 当使用post()发送消息时, 最后会调用runnable.run()回调。sendMessage()则是执行handleMessage(), 这个就是我们构建对象时重写的方法

public void dispatchMessage(Message msg) {  
    if (msg.callback != null) {  
        handleCallback(msg);  
    } else {  
        if (mCallback != null) {  
            if (mCallback.handleMessage(msg)) {  
                return;  
            }  
        }  
        handleMessage(msg);  
    }  
}
private static void handleCallback(Message message) {
    message.callback.run();
}

2. 深入native层

2.1 Looper.cpp

Java层的Looper主要是负责从MessageQueue中循环读取消息分发给Handler处理 Native层Looper主要是负责监听ReadPipe(读管道),发送消息(Java中是由Handler处理的)

  • 构造函数
Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    int wakeFds[2];
    // 创建一个管道
    int result = pipe(wakeFds);
    // 管道读端
    mWakeReadPipeFd = wakeFds[0];
    // 管道写端
    mWakeWritePipeFd = wakeFds[1];
    // 给读管道设置非阻塞的flag, 保证在没有缓冲区可读的情况下立即返回而不阻塞。
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    // 同理给写管道设置非阻塞
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
#ifdef LOOPER_USES_EPOLL
    // 分配epoll实例,注册唤醒管道并监听
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    // 定义监听事件
    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event));
    // 监听EPOLLIN类型事件, 该事件表示对应的文件有数据可读
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeReadPipeFd;
    // 注册监听事件, 这里只监听mWakeReadPipeFd
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
#else
    // Add the wake pipe to the head of the request list with a null callback.
    ...
#endif
#ifdef LOOPER_STATISTICS
    ...
#endif
}
  • Looper::getForThread(); Looper::setForThread();
// 将Looper放入到线程中
void Looper::setForThread(const sp<Looper>& looper) {
    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
    // 增加新引用的计数
    if (looper != NULL) {
        looper->incStrong((void*)threadDestructor);
    }
    // 将新的Looper对象设置到线程局部对象
    pthread_setspecific(gTLSKey, looper.get());
    // 减少老引用的计数
    if (old != NULL) {
        old->decStrong((void*)threadDestructor);
    }
}

static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
// 获取线程中的Looper
sp<Looper> Looper::getForThread() {
    // initTLSKey 指代 initTLSKey()函数 内部调用pthread_key_create(...)创建线程局部对象
    // PTHREAD_ONCE_INIT  在Linex 线程模型中表示在本线程只执行一次
    int result = pthread_once(& gTLSOnce, initTLSKey);
    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
    // 返回线程局部对象中的Looper对象
    return (Looper*)pthread_getspecific(gTLSKey);
}
  • Looper::wake() 唤醒
void Looper::wake() {
    ...
    ssize_t nWrite;
    do {
        // 向管道写入字符串"W"
        // Looper监听了读管道,当有数据写入时,即有数据可读,处理消息的现场就会因为I/O事件被唤醒
        nWrite = write(mWakeWritePipeFd, "W", 1);
    } while (nWrite == -1 && errno == EINTR);
    if (nWrite != 1) {
        if (errno != EAGAIN) {
            LOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}
  • Looper::pollOnce();
inline int pollOnce(int timeoutMillis) {
    return pollOnce(timeoutMillis, NULL, NULL, NULL);
}
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        // 处理Response, mResponses由Looper:pushResponse方法填充
        // 创建Looper对象时mResponseIndex = 0
        // 这个循环只是返回了Response对应请求的标识信息ident
        // Response的处理由pollInner方法完成
        while (mResponseIndex < mResponses.size()) {
            const Response& response = mResponses.itemAt(mResponseIndex++);
            ALooper_callbackFunc callback = response.request.callback;
            if (!callback) {
                int ident = response.request.ident;
                int fd = response.request.fd;
                int events = response.events;
                void* data = response.request.data;
                ...
                if (outFd != NULL) *outFd = fd;
                if (outEvents != NULL) *outEvents = events;
                if (outData != NULL) *outData = data;
                return ident;
            }
        }
        if (result != 0) { // result由pollInner赋值, 默认 = 0
            ...
            if (outFd != NULL) *outFd = 0;
            if (outEvents != NULL) *outEvents = NULL;
            if (outData != NULL) *outData = NULL;
            return result;
        }
        result = pollInner(timeoutMillis);
    }
}
  • Looper::pollInner()
int Looper::pollInner(int timeoutMillis) {
    ...
    // 根据下一条消息的到期时间调整超时时间。
    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
        if (messageTimeoutMillis >= 0
                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
            timeoutMillis = messageTimeoutMillis;
        }
        ...
    }
    // Poll.
    int result = ALOOPER_POLL_WAKE;
    mResponses.clear();
    mResponseIndex = 0;
    ...
#ifdef LOOPER_USES_EPOLL
    // 使用了Linux的epoll机制, 调用epoll_wait监听mEpollFd上的事件。mEpollFd在创建Looper时创建
    // 若果没有事件发生, 将在epoll_wait中等待,时间就是timeoutMillis
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
#else
    // Wait for wakeAndLock() waiters to run then set mPolling to true.
    mLock.lock();
    while (mWaiters != 0) {
        mResume.wait(mLock);
    }
    mPolling = true;
    mLock.unlock();
    size_t requestedCount = mRequestedFds.size();
    int eventCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
#endif
    mLock.lock();
    // 出错或者超时,跳Done
    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }
        result = ALOOPER_POLL_ERROR;
        goto Done;
    }
    if (eventCount == 0) {
        ...
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }
    ...
#ifdef LOOPER_USES_EPOLL
    // 处理所有事件
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
                ...
            }
        } else {
            // 监听的其他文件描述符所发出的请求
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
                // 先不处理, 放入到mResponse中
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
                ...
            }
        }
    }
Done: ;
    // 忽略不看其他类型的epoll events
    ....
    // 具体处理Message和Request
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        // 处理Native层的消息
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();
                ...
                handler->handleMessage(message); // 处理消息
            } // release handler
            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // 设置下次唤醒时间
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }
    mLock.unlock();
    // Invoke all response callbacks.
    for (size_t i = 0; i < mResponses.size(); i++) {
        const Response& response = mResponses.itemAt(i);
        ALooper_callbackFunc callback = response.request.callback;
        if (callback) {
            int fd = response.request.fd;
            int events = response.events;
            void* data = response.request.data;
            ...
            int callbackResult = callback(fd, events, data);
            if (callbackResult == 0) {
                removeFd(fd);
            }
            result = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}
  • Looper::sendMessage() Native层发送消息

2.2 android_os_MessageQueue.cpp

这里其实也实现了和Java层Looper.prepare()方法相同的功能

  • 构造函数
NativeMessageQueue::NativeMessageQueue() {
    // 查询是否存在
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        // 没有就创建Looper
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}
  • android_os_MessageQueue_nativeInit()
/**
 * 创建一个NativeMessageQueue对象
 * 将Java层与Native层的MessageQueue关联起来
 * 从而在Java层中可以通过mPtr成员变量来访问Native层的NativeMessageQueue对象
 * [obj]: 表示调用native 的Java类
 */
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
    // JNI层创建一个NativeMessageQueue对象
    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
    if (! nativeMessageQueue) {
        jniThrowRuntimeException(env, "Unable to allocate native queue");
        return;
    }
    // 将Java层与Native层的MessageQueue关联起来
    android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}

static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
        NativeMessageQueue* nativeMessageQueue) {
        // SetIntField是JNI层向Java传输数据的方法。
        // 这里将nativeMessageQueue的地址保存到Java层MessageQueue对象的mPtr成员变量中
    env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
             reinterpret_cast<jint>(nativeMessageQueue));
}

static struct {
    // jfieldID表示Java层成员变量的名字,因此这里指代Java层MessageQueue对象的mPtr成员变量
    jfieldID mPtr;   // native object attached to the DVM MessageQueue
} gMessageQueueClassInfo;
  • android_os_MessageQueue_nativeWake
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
    // ptr 是java层MessageQueue的mPtr成员变量,存储了JNI层创建的 NativeMessageQueue的地址
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    return nativeMessageQueue->wake();
}

// 最终调用了JNI Looper的wake方法
void NativeMessageQueue::wake() {
    mLooper->wake();
}
  • android_os_MessageQueue_nativePollOnce()
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
        jint ptr, jint timeoutMillis) {
    // 根据mPtr找到 nativeMessageQueue
    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
    nativeMessageQueue->pollOnce(timeoutMillis);
}
void NativeMessageQueue::pollOnce(int timeoutMillis) {
    // 转发给Looper对象处理
    mLooper->pollOnce(timeoutMillis);
}

3. ~!@#¥%……&*(

HandleThread

主要和Handle结合使用来处理异步任务

- 实质是一个Thread, 继承自Thread
- 他拥有自己的Looper对象
- 必须调用HandleThread.start()方法, 因为在run中创建Looper对象

IdleHandler

  • 使用场景:
- 主线程加载完页面之后,去加载一些二级界面;
- 管理一些任务, 空闲时触发执行队列。
  • Handler线程空闲时执行:
- 线程的消息队列为空
- 消息队列头部的处理时间未到
  • 使用

可以参考ActivityThread类中的空闲时执行gc流程

class IdleForever implements MessageQueue.IdleHandler {
    /**
     * @return true : 保持此Idle一直在Handler中, 每次线程执行完后都会在这执行.
     */
    @Override
    public boolean queueIdle() {
        Log.d("", "我,天地难葬!");
        return true;
    }

}

class IdleOnce implements MessageQueue.IdleHandler {
    /**
     * @return false : 执行一次后就从Handler线程中remove掉。
     */
    @Override
    public boolean queueIdle() {
        Log.d("", "我真的还想再活五百年~!!!");
        return false;
    }
}

苦工 : 口戛口崩月危.Z