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

相关推荐
Jeled1 小时前
「高级 Android 架构师成长路线」的第 1 阶段 —— 强化体系与架构思维(Clean Architecture 实战)
android·kotlin·android studio·1024程序员节
明道源码3 小时前
Kotlin 控制流、函数、Lambda、高阶函数
android·开发语言·kotlin
消失的旧时光-19435 小时前
Kotlin × Gson:为什么遍历 JsonObject 要用 entrySet()
android·kotlin·数据处理·1024程序员节
G果6 小时前
安卓APP页面之间传参(Android studio 开发)
android·java·android studio
曾凡宇先生7 小时前
无法远程连接 MySQL
android·开发语言·数据库·sql·tcp/ip·mysql·adb
zhangphil9 小时前
Android GPU的RenderThread Texture upload上传Bitmap优化prepareToDraw
android
柿蒂10 小时前
聊聊SliverPersistentHeader优先消费滑动的设计
android·flutter
假装多好12312 小时前
android三方调试几个常用命令
android·1024程序员节·三方,gms
侧耳42912 小时前
android11禁止安装apk
android·java·1024程序员节
JohnnyDeng9413 小时前
ArkTs-Android 与 ArkTS (HarmonyOS) 存储目录全面对比
android·harmonyos·arkts·1024程序员节