消息处理机制之消息队列

Android中消息处理机制主要围绕消息队列来实现的。一个线程拥有一个消息队列之后,就可以进入到一个消息循环中,同时其他线程以及线程本身可以往这个消息队列发送消息,以便在这个消息被处理时执行一个特定的操作。

Android系统主要是通过MessageQueue、Looper和Handler三个类实现消息处理机制的。其中MessageQueue来描述消息队列;Looper类用来创建消息队列以及消息循环;Handler用来发送消息和处理消息。

先看一个典型的Looper线程实例

class LooperThread extends Thread {
        public Handler mHandler;
         
         public void run() {
             Looper.prepare();
             mHandler = new Handler() {
                 public void handleMessage(Message msg) {
                     // process incoming messages here
                 }
             };
             Looper.loop();
         }
     }

从实例中看出我们先调用了Looper.prepare()在其中会创建消息队列,Looper.loop()在其中会进行消息循环的过程。Handler进行消息的发送和处理

一、创建线程消息队列

Android 中消息队列是使用MessageQueue对象来描述的,它是在Looper的构造方法中创建的,可以通过调用looper的静态方法prepareMainLooper和prepare方法来实例化Looper。

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

public final class Looper {
     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class
    final MessageQueue mQueue;
    
     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));
    }

    /**
     * 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 new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    /**
     * Returns the application's main looper, which lives in the main thread of the application.
     */
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }
    
}

Looper类有一个类型为ThreadLocal的静态成员变量sThreadLocal,用来保存线程中的Looper对象。在Looper的静态成员函数prepare方法中,if语句会检查当前线程是否已经存在Looper对象,如果存在就会抛出异常;否则就会创建Looper实例并将它保存在Looper的静态成员变量sThreadLocal中。

prepareMainLooper()方法只能有系统调用,用来创建我们应用程序主线程的消息队列。Androidxitpng 是在ActivityThread的静态成员函数main方法中调用的。

一个looper对象在创建过程中,会在构造方法中创建一个MessageQueue对象,并且保存在成员变量mQueue中

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
 MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }

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

static const JNINativeMethod gMessageQueueMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
    { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
    { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },
    { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake },
    { "nativeIsPolling", "(J)Z", (void*)android_os_MessageQueue_nativeIsPolling },
    { "nativeSetFileDescriptorEvents", "(JII)V",
            (void*)android_os_MessageQueue_nativeSetFileDescriptorEvents },
};

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

在MessagQueue对象的构造方法中调用nativeInit JIN方法在此方法中创建了NativeMessageQueue对象。在register_android_os_MessageQueue方法中mPtr指向了java中MessageQueue的成员变量mPtr

NativeMessageQueue对象在创建的过程中,又会在内部调用C++的Looper对象

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

首先调用C++层的Looper类的静态成员函数getForThread()来获取当前线程的Looper对象。如果没有创建过就会创建一个C++层的Looper对象,并保存在NativeMessageQueue类的成员变量mLooper中,然后调用Looper的静态函数setForThread将当前线程关联起来。

C++ Looper类的创建过程中,又在内部创建一个管道

Looper::Looper(bool allowNonCallbacks)
    : mAllowNonCallbacks(allowNonCallbacks),
      mSendingMessage(false),
      mPolling(false),
      mEpollRebuildRequired(false),
      mNextRequestSeq(0),
      mResponseIndex(0),
      mNextMessageUptime(LLONG_MAX) {
    mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
    LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0, "Could not make wake event fd: %s", strerror(errno));

    AutoMutex _l(mLock);
    rebuildEpollLocked();
}

void Looper::rebuildEpollLocked() {
    // Close old epoll instance if we have one.
    if (mEpollFd >= 0) {
        mEpollFd.reset();
    }

    // Allocate the new epoll instance and register the wake pipe.
    mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(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.get();
    int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",
                        strerror(errno));

    for (size_t i = 0; i < mRequests.size(); i++) {
        const Request& request = mRequests.valueAt(i);
        struct epoll_event eventItem;
        request.initEventItem(&eventItem);

        int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
        if (epollResult < 0) {
            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",
                  request.fd, strerror(errno));
        }
    }
}

在Looper中会创建mWakeEventFd,它是unique_fd类型的,在其中会创建一个管道。这个管道在消息循环中起到的作用非常大。首先当一个线程没有消息需要处理是,它就会睡眠在这个管道的读端文件描述符上,直到有新的消息需要处理为止;其次当其他线程向这个线程的消息队列发送一个消息之后,其他线程就会通过这个写端文件描述符往这个管道写入一个数据,从而将这个线程唤醒,以便对刚才发送到消息队列中的消息进行处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值