Android事件传递机制
来源:互联网 发布:mac书名号怎么打出来 编辑:程序博客网 时间:2024/05/21 06:15
1.本想从底层开始看看Android的事件是怎么产生的,怎么从底层传到window的,但是 一位网友的总结:Linux Kernel将rawinputevent写入到设备节点后,InputReader会通过EventHub将原始事件读取出来并翻译加工为Android输入事件,而后把它交给InputDispatcher。InputDispatcher根据WMS(WindowManagerService)提供的窗口信息将事件传递给合适的窗口,若窗口为壁纸/SurfaceView等,则到了终点;否则会由该Window的ViewRoot继续分发到合适的View。
2.还是从window开始吧。当原始事件进入InputDispatcher时,已被加工为KeyEvent、MotionEvent(或SwitchEvent)。而后InputDispatcher会对事件进行进一步分发。
将事件放入派发队列
将输入事件加入到派发队列后,会依次执行以下步骤:
- 派发线程开始派发事件;
- 锁定目标窗口,然后向目标Window发送事件。
- InputDispatcher通过InputChannel将event发给Window(InputDispatcher运行于system_server进程中,Window运行于应用进程,两者通过InputChannel通信。);
- Window端的Looper被唤醒,从InputChannel中读取一个InputEvent,而后调用onInputEvent(ev)。具体来说是调用ViewRootImpl的mInputEventReceiver的成员的onInputEvent()方法。
- 调用doProcessInputEvents()
- 调用deliverInputEvent()
在Android系统中,对系统中的所有窗口进行管理是窗口管理服务WindowManagerService的职责(wms)。
在Android中界面的呈现是由Activity完成的
我们知道这个DecorView才是我们看到的显示界面 所以可以理解为用户的触摸按键的消息是由windowManagerService捕捉到然后交给phoneWindow中的DecorView进行相应的处理,而连接两者的桥梁则是一个ViewRoot类,ViewRoot类由windowManagerService创建。
这个ViewRoot可以
- 向DecorView分发收到的用户发起的event事件,如按键,触屏,轨迹球等事件
- 与WindowManagerService交互,完成整个Activity的GUI的绘制。
这里就不去谈Viewrootimpl是如何与WindowManagerService完成GUI的绘制了
在ViewRootImpl中包含有一个WindowInputEventReceiver对象,我们从名字都可以大致的知道它是一个接受用户事件的类,它是Viewrootimpl的一个内部类
final class WindowInputEventReceiver extends InputEventReceiver { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); } @Override public void onInputEvent(InputEvent event) { enqueueInputEvent(event, this, 0, true); } @Override public void onBatchedInputEventPending() { if (mUnbufferedInputDispatch) { super.onBatchedInputEventPending(); } else { scheduleConsumeBatchedInput(); } } @Override public void dispose() { unscheduleConsumeBatchedInput(); super.dispose(); } }
我们来看看他是如何接受到事件,如何传递给DecorView的。
1 首先看看它老汉的构造方法:
public InputEventReceiver(InputChannel inputChannel, Looper looper) { //... 省掉判断是否为null的方法 // 用来传递消息 mInputChannel = inputChannel; mMessageQueue = looper.getQueue(); mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this), inputChannel, mMessageQueue); mCloseGuard.open("dispose"); }
我们可以看出接受事件肯定和InputChannel,mMessageQueue相关(具体是什么关系下来在研究一下)
2 看看WindowInputEventReceiver中的方法
onInputEvent(InputEvent event)
该方法中调用了
void enqueueInputEvent(InputEvent event, InputEventReceiver receiver, int flags, boolean processImmediately) { adjustInputEventForCompatibility(event); QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags); QueuedInputEvent last = mPendingInputEventTail; if (last == null) { mPendingInputEventHead = q; mPendingInputEventTail = q; } else { last.mNext = q; mPendingInputEventTail = q; } mPendingInputEventCount += 1; Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName, mPendingInputEventCount); if (processImmediately) { // 立即处理事件 doProcessInputEvents(); } else { // 将事件放到队列的最后 scheduleProcessInputEvents(); } }
这俩种方式最后都会调用deliverInputEvent(QueuedInputEvent q)方法传送事件
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent", q.mEvent.getSequenceNumber()); if (mInputEventConsistencyVerifier != null) { //验证事件 根据不同的情况验证 onKeyEvent(keyEvent, nestingLevel); // onTouchEvent(motionEvent, nestingLevel); onGenericMotionEvent(motionEvent, //nestingLevel);onTrackballEvent(motionEvent, nestingLevel); mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0); } InputStage stage; if (q.shouldSendToSynthesizer()) { //从新输入事件处理输入事件 stage = mSyntheticInputStage; } else { //ture?Performs early processing of post-ime input events:Delivers pre-ime //Finput events to a native activity* Does not support pointer events. stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage; } if (stage != null) { stage.deliver(q); } else { finishInputEvent(q); }
各种调用 最后调用InputMethodManager中的dispatchInputEvent方法 或者View.dispatchPointerEvent
终于跑到View上面来了!!!
public final boolean dispatchPointerEvent(MotionEvent event) { if (event.isTouchEvent()) { return dispatchTouchEvent(event); } else { return dispatchGenericMotionEvent(event); } }
onBatchedInputEventPending()dispose()
事件在View上传递网上的资料有点多了 这里就暂时不去分析它了!
- android 事件传递机制
- android 事件传递机制
- android事件传递机制
- Android事件传递机制
- Android 事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- Android事件传递机制
- 算法学习之显著性检测
- 数据库端口3306被占用
- tomcat的域名以及多域名配置
- requirejs入门
- python进阶12:单下划线与双下划线(私有和保护)
- Android事件传递机制
- 第四十一章 SpringBoot SpringMVC配置
- adb命令填充空间
- PLSQL Table Collection Cursor Variable
- androidStudio使用eclipse的快捷键
- Oracle 用户(user)和模式(schema)的区别
- 分组函数group by用法
- 第四十二章 SpringBoot注册Servlet/Filter/Listener
- JDK核心JAVA源码解析(1)