android消息机制原理

android消息机制原理

在android框架或者应用程序开发中,随处可见Handler类和Looper类的使用,对应用程序而言,它的主类,也就是入口,是框架层的ActivityThread.java 类,当应用程序被启动之后就会进入ActivityThread的main方法

public static void main(String[] args) {
      ....
        Looper.prepareMainLooper();//创建消息队列

        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ....
        Looper.loop();//创建消息循环
    }
}

SystemServer进程和所有的应用程序进程都是通过消息来驱动,系统为每个用用程序和SystemServer进程维护一个消息队列和消息循环,而应用程序和SystemServer进程的主线程通过循环不断的从这消息队列中获取消息,然后对获取的消息就行处理,这样就实现了通过消息来驱动应用程序和SystemServer进程的执行,这就是android消息处理机制,android消息机制由四个重要的类组成,分别是消息Message,消息队列MessageQueue,消息循环Looper,消息的发送和处理者Handler。
在消息处理机制中,消息都存放在一个消息队列中,应用程序和SystemServer进程的主线程围绕着这个消息队列进入一个无限循环,直到应用程序和SystemServer进程退出。当应用程序和SystemServer进程的Handler向消息队列发送了一个消息之后,消息队列中就有消息了,这个时候应用程序和SystemServer进程的主线程会把这个消息取出来,并分发给相应的handler进行处理,如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来,因此,android系统消息机制的核心是
1.创建消息队列,之后进入无限循环读取消息
2.发送消息
3.处理消息,当发送消息之后,无限循环读到这个消息,之后就分给相应的处理者来处理

创建消息队列和进入消息循环

该过程的序列图:

Created with Raphaël 2.1.2 ActivityThread main() ActivityThread main() Looper Looper MessageQueue MessageQueue android_os_MessageQueue android_os_MessageQueue Looper.cpp Looper.cpp prepareMainLooper new MessageQueue nativeInit nativeInit new NativeMessageQueue() new Looper(false) rebuildEpollLocked loop next android_os_MessageQueue_nativePollOnce pollOnce pollOnce pollInner awoken()

下面从code的角度开始分析这个流程:

public static void main(String[] args) {
      ....
        Looper.prepareMainLooper();//创建消息队列

        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ....
        Looper.loop();//创建消息循环
    }
}

ActivityThread的main()方法首先创建一个ActivityThread的实例,然后创建一个消息队列,和消息循环,接下来分析Looper.prepareMainLooper()消息队列和 Looper.loop()消息循环

  public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
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类中的变量mQueue 是一个消息队列,所有的消息都放在这个队列中,变量sThreadLocal表示目前线程,即应用程序的主线程。
当创建Looper对象的时候调用它的构造方法来创建一个消息队列MessageQueue,并赋值给Looper的mQueue ,创建MessageQueue就会进入MessageQueue的构造方法,

MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }

在MessageQueue的构造方法中,调用了nativeInit方法,而这个方法是一个native方法,接下来就看这个native方法的实现

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

这个方法里面new关键字又创建了一个NativeMessageQueue队列,接下来看一下NativeMessageQueue类的构造方法

NativeMessageQueue::NativeMessageQueue() :
        mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
    mLooper = Looper::getForThread();
    if (mLooper == NULL) {
        mLooper = new Looper(false);
        Looper::setForThread(mLooper);
    }
}

NativeMessageQueue的构造方法中,创建了一个native的Looper对象,它与java层的Looper不一样,但是他们是一一对应的。通过看Looper代码,发现android消息机制的核心就在native的Looper中,

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd.  errno=%d", errno);

    AutoMutex _l(mLock);
    rebuildEpollLocked();
}

looper的构造方法中首先调用eventfd函数创建一个文件描述符mWakeEventFd ,这个文件描述符被用户当做一个事件的等待/响应机制,靠内核去响应用户事件,而参数EFD_NONBLOCK类似于O_NONBLOCK标志,用来设置文件描述符,主要是为了节省对fcntl的额外调用,最后,Looper的构造函数调用rebuildEpollLocked函数来进一步处理:

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd.  errno=%d", errno);

    AutoMutex _l(mLock);
    rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
    // Allocate the new epoll instance and register the wake pipe.
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeEventFd;
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance.  errno=%d",
            errno);
}

这个方法是android消息机制的核心所在,
eppol机制:它是一种I/O多路复用技术,是select/poll的加强版,使用epoll会涉及到epoll_create(),epoll_ctl().epoll_wait()这三个重要的函数
epoll_create:创建epoll文件描述符
epoll_ctl:设置监控文件描述符
epoll_wait:等待监控文件描述符发生IO事件
mEpollFd 表示这个文件描述符上最多可以监控8文件描述符接着调用epoll_ctl()函数来告诉epoll监控mEpollFd 文件描述符的什么事件,在这里就是监控mWakeEventFd文件描述符的EPOLL_CTL_ADD事件,当mWakeEventFd有事件触发的时候,就会唤醒正在等待的线程
接下来看一下消息循环loop()

  public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
             msg.target.dispatchMessage(msg);
     }

当没有消息的时候就return回去,当有消息的时候就获得这个消息,并调用msg的target对象的dispatchMessage方法处理消息,target是一个handler对象,它的值就是应用程序中用来send message的Handler而对象,

  Message next() {
    ...
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            nativePollOnce(ptr, nextPollTimeoutMillis);
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                去检查一个下次,如果没有发现就返回
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
           ....

循环中nativePollOnce是一个native方法,它查看当前消息队列中是否有消息,如果有消息就获得,如果没有消息就等待,

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

android_os_MessageQueue_nativePollOnce方法调用native的nativeMessageQueue对象的pollOnce方法进一步处理,pollOnce()方法中有这一句代码mLooper->pollOnce(timeoutMillis);然后由looper中的pollOnce,然后调用了 pollInner(timeoutMillis)继续处理

int Looper::pollInner(int timeoutMillis) {
    ....
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    ...
     // 说明发生了错误
    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }
        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
        result = POLL_ERROR;
        goto Done;
    }

    //说明超时了
    if (eventCount == 0) {
#if DEBUG_POLL_AND_WAKE
        ALOGD("%p ~ pollOnce - timeout", this);
#endif
        result = POLL_TIMEOUT;
        goto Done;
    }
...
    for (int i = 0; i < eventCount; i++) {//说明有事件发生
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeEventFd) {
            if (epollEvents & EPOLLIN) {
                awoken();//读取事件
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
            }
        } else {
            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
                        "no longer registered.", epollEvents, fd);
            }
        }

当eventCount大于0的时候,说明有时间发生,调用awoken()读取事件

void Looper::awoken() {
#if DEBUG_POLL_AND_WAKE
    ALOGD("%p ~ awoken", this);
#endif

    uint64_t counter;
    TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
}

awoken() 函数通过read函数读出这个事件,这个事件在应用程序发送消息的时候写进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值