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

相关推荐
张风捷特烈7 小时前
Flutter 伪3D绘制#03 | 轴测投影原理分析
android·flutter·canvas
omegayy10 小时前
Unity 2022.3.x部分Android设备播放视频黑屏问题
android·unity·视频播放·黑屏
mingqian_chu10 小时前
ubuntu中使用安卓模拟器
android·linux·ubuntu
自动花钱机10 小时前
Kotlin问题汇总
android·开发语言·kotlin
行墨13 小时前
Kotlin 主构造函数
android
前行的小黑炭13 小时前
Android从传统的XML转到Compose的变化:mutableStateOf、MutableStateFlow;有的使用by有的使用by remember
android·kotlin
_一条咸鱼_13 小时前
Android Compose 框架尺寸与密度深入剖析(五十五)
android
在狂风暴雨中奔跑13 小时前
使用AI开发Android界面
android·人工智能
行墨13 小时前
Kotlin 定义类与field关键
android
信徒_14 小时前
Mysql 在什么样的情况下会产生死锁?
android·数据库·mysql