这里,我们考虑一个问题,Android中的应用是一个looper线程,没有任务时就阻塞着,其他线程通过handler调用等方式向主线程looper发送任务,
如果点击应用上的按钮,应用是怎么及时响应的呢,
是专门启动了一个额外的线程去监控input事件么?
这里直接给出答案,input事件传送给了系统IMS,IMS通过inputchannel把input传送给应用,而应用中的主线程looper监控了inputchannel的fd,
这里看一下主线程looper是怎么实现的监控inputchannel的fd。
在应用创建的时候,会调用ViewRootImpl的serView方法,
frameworks/base/core/java/android/view/ViewRootImpl.java
setView
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
这里传入了主线程的looper给WindowInputEventReceiver
这个构造方法,调用其父类的构造
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
mInputChannel, mMessageQueue);
mCloseGuard.open("InputEventReceiver.dispose");
}
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
std::shared_ptr<InputChannel> inputChannel =
android_view_InputChannel_getInputChannel(env, inputChannelObj);
if (inputChannel == nullptr) {
jniThrowRuntimeException(env, "InputChannel is not initialized.");
return 0;
}
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
其中,receiver->initialize();
调用到
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
auto&& fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd.get(), 0, events, this, nullptr);
} else {
mMessageQueue->getLooper()->removeFd(fd.get());
}
}
这里,打不过就加入,把inputchannel的fd也加入到主线程looper的epool监控之中。