【Android】app中阻塞的looper为什么可以响应touch事件

发布时间:2024年01月21日

这里,我们考虑一个问题,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监控之中。

文章来源:https://blog.csdn.net/aaajj/article/details/135730746
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。