這里,我們考慮一個問題,Android中的應(yīng)用是一個looper線程,沒有任務(wù)時就阻塞著,其他線程通過handler調(diào)用等方式向主線程looper發(fā)送任務(wù),
如果點(diǎn)擊應(yīng)用上的按鈕,應(yīng)用是怎么及時響應(yīng)的呢,
是專門啟動了一個額外的線程去監(jiān)控input事件么?
這里直接給出答案,input事件傳送給了系統(tǒng)IMS,IMS通過inputchannel把input傳送給應(yīng)用,而應(yīng)用中的主線程looper監(jiān)控了inputchannel的fd,
這里看一下主線程looper是怎么實(shí)現(xiàn)的監(jiān)控inputchannel的fd。
在應(yīng)用創(chuàng)建的時候,會調(diào)用ViewRootImpl的serView方法,
frameworks/base/core/java/android/view/ViewRootImpl.java
setView
mInputEventReceiver = new?WindowInputEventReceiver(inputChannel,
Looper.myLooper());
這里傳入了主線程的looper給WindowInputEventReceiver
這個構(gòu)造方法,調(diào)用其父類的構(gòu)造
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");
}文章來源:http://www.zghlxwxcb.cn/news/detail-816053.html
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();
調(diào)用到
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監(jiān)控之中。文章來源地址http://www.zghlxwxcb.cn/news/detail-816053.html
到了這里,關(guān)于【Android】app中阻塞的looper為什么可以響應(yīng)touch事件的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!