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

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

相关推荐
拭心9 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王12 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡12 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道12 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库13 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道14 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe14 小时前
Android Hook - 动态加载so库
android
居居飒15 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He18 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗18 小时前
Android笔试面试题AI答之Android基础(1)
android