Android Framework-Input-6 事件分发到View

290 阅读2分钟

开局叠甲,可能理解有误,请大佬们斧正。

前面我们追到android_view_InputEventReceiverconsumeEvents()方法, 那么这个事件是怎么分发到View的?

//android_view_InputEventReceiver.cpp
consumeEvents(){
   env->CallVoidMethod(receiverObj.get(),
                                    gInputEventReceiverClassInfo.onBatchedInputEventPending,
                                    mInputConsumer.getPendingBatchSource());
}

这里调用JNI会回调WindowInputEventReceiver 注意WindowInputEventReceiver 是继承了InputEventReceiver

-->WindowInputEventReceiver.onBatchedInputEventPending()
  -->consumeBatchedInputEvents(-1);
  -->nativeConsumeBatchedInputEvents(mReceiverPtr, frameTimeNanos);
//再次回到android_view_InputEventReceiver.cpp
    -->  nativeConsumeBatchedInputEvents(){
    status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos,
            &consumedBatch);
  }

--> env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
//再次调回InputEventReceiver,因为WindowInputEventReceiver没重载该方法
-->InputEventReceiver.dispatchInputEvent(){
  //seq 很重要
  mSeqMap.put(event.getSequenceNumber(), seq);
        onInputEvent(event);
}
//因为我们是 WindowInputEventReceiver 

--> WindowInputEventReceiver.onInputEvent()

调用到这里onInputEvent()接下来调用链条如下

//ViewRootImpl
  // enqueueInputEvent(event, this, 0, true);
   --> enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately){
    if (processImmediately) {
      //走立马处理
            doProcessInputEvents();
        } else {
            scheduleProcessInputEvents();
        }
  
}

-->deliverInputEvent()

-->stage.deliver(q);

-->onProcess(q);

onProcess(q) 这里会依次走 EarlyPostImeInputStage/NativePostImeInputStage/ViewPostImeInputStage, 这是因为在setView()使用了责任链倒置模式。

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,  
int userId) {
//省略
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);  
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,  
"aq:native-post-ime:" + counterSuffix);  
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);  
InputStage imeStage = new ImeInputStage(earlyPostImeStage,  
"aq:ime:" + counterSuffix);  
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);  
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,  
"aq:native-pre-ime:" + counterSuffix);
//省略
}

ViewPostImeInputStageonProcess() 调用 processPointerEvent(q);

final class ViewPostImeInputStage extends InputStage {  
public ViewPostImeInputStage(InputStage next) {  
super(next);  
}  
  
@Override  
protected int onProcess(QueuedInputEvent q) {  
if (q.mEvent instanceof KeyEvent) {  
      return processKeyEvent(q);  
} 
else {  
     final int source = q.mEvent.getSource();  
       if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {  
    return processPointerEvent(q);  
   } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {  
    return processTrackballEvent(q);  
   } 
   else {  
    return processGenericMotionEvent(q);  
   }  
  }  
}

processPointerEvent(q)里面调用了mView.dispatchPointerEvent(event);将事件传递给了mView,我们知道其实这里的mView 是布局构建出来的,接下来就会走到我们常说的事件分发机制。 注意最后返回的是FINISH_HANDLED ,后面要用到的。


private int processPointerEvent(QueuedInputEvent q) {  
final MotionEvent event = (MotionEvent)q.mEvent;  
  
mAttachInfo.mUnbufferedDispatchRequested = false;  
mAttachInfo.mHandlingPointerEvent = true;  
boolean handled = mView.dispatchPointerEvent(event);  
maybeUpdatePointerIcon(event);  
maybeUpdateTooltip(event);  
mAttachInfo.mHandlingPointerEvent = false;  
if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {  
mUnbufferedInputDispatch = true;  
if (mConsumeBatchedInputScheduled) {  
scheduleConsumeBatchedInputImmediately();  
}  
}  
return handled ? FINISH_HANDLED : FORWARD;  
}

到此 ,我们大体明白分发下来的事件是怎么从Nativie 到达了Java层,进入了我们常说的事件分发。下一步我们将看事件的销毁和ANR相关。