android应用消息处理机制

本文详细介绍了Android的消息处理机制,包括消息循环、消息发送和消息处理三个核心部分。消息循环通过Looper类和MessageQueue实现,利用了Linux的pipe通信机制及Epoll的epoll_wait进行等待。消息发送通过Handler的enqueueMessage方法将Message插入队列,并通过nativeWake唤醒线程。消息处理由Looper.loop中的dispatchMessage完成,遵循谁发送谁处理的原则。整个过程涉及线程同步、管道通信和事件监听等技术。
摘要由CSDN通过智能技术生成

2月份写的文章.发上来.


Android的消息处理机制由三部分组成:消息循环、消息发送、消息处理。

消息循环

消息都存在在一个消息队列中,应用程序的主线程会不断读取其中的消息,并分派给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就进入空闲等待状态。

消息循环通过Looper类来实现。

这里分两部分

一.Looper.prepareMainLooper

二.Looper.loop

Looper.prepareMainLooper

public final class Looper {

……

//sThreadLocal.get() will return null unless you've called prepare().

static finalThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

private staticLooper sMainLooper;  // guarded byLooper.class

 

finalMessageQueue mQueue;

……

/** Initialize the current thread as a looper.

     * This gives you a chance to create handlers that then reference

     * this looper, before actually starting the loop. Be sure to call

     * {@link #loop()} after calling this method, and end it by calling

     * {@link #quit()}.

     */

   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 perthread");

       }

       sThreadLocal.set(new Looper(quitAllowed));

    }

 

   /**

    * Initialize the current thread as a looper, marking it as an

    * application's main looper. The main looper for your application

    * is created by the Android environment, so you should never need

    * to call this function yourself. See also: {@link #prepare()}

    */

   public static void prepareMainLooper() {

       prepare(false);

       synchronized (Looper.class) {

           if (sMainLooper != null) {

                throw newIllegalStateException("The main Looper has already been prepared.");

           }

           sMainLooper = myLooper();

       }

}

……

 

   /**

    * Return the Looper object associated with the current thread.  Returns

    * null if the calling thread is not associated with a Looper.

    */

   public static Looper myLooper() {

       return sThreadLocal.get();

}

……

   /**

    * Return the {@link MessageQueue} object associated with the current

    * thread.  This must be calledfrom a thread running a Looper, or a

    * NullPointerException will be thrown.

    */

   public static MessageQueue myQueue() {

       return myLooper().mQueue;

    }

 

   private Looper(boolean quitAllowed) {

       mQueue = new MessageQueue(quitAllowed);

       mThread = Thread.currentThread();

}

 

……

}

 

prepareMainLooper主要做的事情就是:创建了一个Looper对象,保存在sThreadLocal中,并将这个Looper对象赋值给sMainLooper保存起来。

new Looper:在创建的时候,同时实例化一个MessageQueue。并赋值给mQueue保存起来。后续的消息就通过它来管理。

接下来,我们来看MessageQueue.java

------  frameworks/base/core/java/android/os/MessageQueue.java

 

public final class MessageQueue {

……

 

   private native static int nativeInit();

   private native static void nativeDestroy(int ptr);

   private native static void nativePollOnce(int ptr, int timeoutMillis);

   private native static void nativeWake(int ptr);

private nativestatic boolean nativeIsIdling(int ptr);

……

MessageQueue(boolean quitAllowed) {

       mQuitAllowed = quitAllowed;

       mPtr = nativeInit();

}

……

}

可以看出。MessageQueue的整体实现都交给了native.

继续跟,grep一把就可以找到MessageQueue的native实现。

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

从nativeInit开始

static jintandroid_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {

   NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();

   if (!nativeMessageQueue) {

       jniThrowRuntimeException(env, "Unable to allocate nativequeue");

       return 0;

    }

 

   nativeMessageQueue->incStrong(env);

   return reinterpret_cast<jint>(nativeMessageQueue);

}

可以看出,android_os_MessageQueue_nativeInit在native中创建了一个nativeMessageQueue.
在这个文件中可以找到如下

NativeMessageQueue::NativeMessageQueue(): mInCallback(false), mExceptionObj(NULL) {

    mLooper = Looper::getForThread();

    if (mLooper == NULL) {

        mLooper = new Looper(false);

        Looper::setForThread(mLooper);

    }

}

nativeMessageQueue在native层又实例化了一个Looper。

 

Looper.cpp实现在system/core/libutils/Looper.cpp

 

Looper::Looper(boolallowNonCallbacks) :

        mAllowNonCallbacks(allowNonCallbacks),mSendingMessage(false),

        mResponseIndex(0),mNextMessageUptime(LLONG_MAX) {

    int wakeFds[2];

    int result = pipe(wakeFds);

    LOG_ALWAYS_FATAL_IF(result != 0,"Could not create wake pipe. errno=%d", errno);

 

    mWakeReadPipeFd =wakeFds[0];

    mWakeWritePipeFd =wakeFds[1];

 

    result = fcntl(mWakeReadPipeFd, F_SETFL,O_NONBLOCK);

    LOG_ALWAYS_FATAL_IF(result != 0,"Could not make wake read pipe non-blocking.  errno=%d", errno);

 

    result = fcntl(mWakeWritePipeFd, F_SETFL,O_NONBLOCK);

    LOG_ALWAYS_FATAL_IF(result != 0,"Could not make wake write pipe non-blocking.  errno=%d", errno);

 

    mIdling = false;

 

    // Allocate the epoll instance and registerthe wake pipe.

    mEpollFd =epoll_create(EPOLL_SIZE_HINT);//#------ EPOLL_SIZE_HINT是在这个mEpollFd上能监控的最大文件描述符数,这里创建了epollfiledescription

    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 = mWakeReadPipeFd;//#------将mWakeReadPipeFd赋值进去,就是说有内容更新,就立马wake线程去读取。

    result = epoll_ctl(mEpollFd,EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);

    LOG_ALWAYS_FATAL_IF(result != 0,"Could not add wake read pipe to epoll instance.  errno=%d", errno);

}

 

注意看代码中标红部分。

消息的循环使用的是Pipe机制,是linux系统中进程间通信的一种机制。

好像linux进程间的通信总是通过一个文件进行。mWakeReadPipeFd,mWakeWritePipeFd 是pipe的文件描述(FileDescription)。

这是一个多线程机制。

线程A使用FileDescription来读pipe的内容

线程B使用FileDescription来写pipe的内容

Pipe中没内容就线程A就进入wait状态,线程B在进行写操作的时候,就会wake线程A。

 

Epoll这部分不详。直接应用罗大牛的说明

这个等待和唤醒的操作是如何进行的呢,这就要借助Linux系统中的epoll机制了。 Linux

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值