【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监控之中。

相关推荐
CYY9512 小时前
Compose 入门篇
android·kotlin
杉氧16 小时前
Compose 时代的 MVI 架构:如何用单向数据流驱动复杂 UI?
android·架构·android jetpack
杉氧16 小时前
Modifier 的艺术:为什么链式调用的顺序决定了UI 的生命周期?
android·架构·android jetpack
李斯维17 小时前
腾讯 XLog 日志框架 Android 端接入
android·android studio·android jetpack
黄林晴17 小时前
Kotlin Toolchain 0.11 发布:Amper 正式更名,统一 kotlin 命令
android·kotlin
雨白18 小时前
C语言基础快速入门与指针初探
android
Exploring20 小时前
避坑指南:升级 AGP 8.0+ 导致第三方 SDK 编译崩溃的完美解决方案
android
石山岭2 天前
自己动手写了一个 Android 虚拟定位 App:GPSSimulate 技术实
android·前端
杉氧2 天前
副作用 (Side Effects) 全攻略:如何像大师一样掌控 Composable 的生命周期?
android·架构·android jetpack
Kapaseker2 天前
Kotlin Toolchain 0.11 发布:主要是把 Amper 干没了
android·kotlin