先上流程图

Android Input事件APP端流程分析_第1张图片

WindowInputEventReceiverWindowInputEventReceiver为InputEventReceiver的子类是接收InputManagerService派发事件的APP端,在InputEventReceiver.cpp 中可以看到 接收到input事件后回调Java层的dispatchInputEvent 即 InputEventReceiver的dispatchInputEvent 方法,dispatchInputEvent 调用onInputEvent方法,onInputEvent进行重写,即调用WindowInputEventReceiver的onInputEvent
InputEventReceiver.cppstatus_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {//........            if (inputEventObj) {                if (kDebugDispatchCycle) {                    ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());                }//回调Java层dispatchInputEvent                 env->CallVoidMethod(receiverObj.get(),                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);              //.............    }}InputEventReceiver.java private void dispatchInputEvent(int seq, InputEvent event, int displayId) {        mSeqMap.put(event.getSequenceNumber(), seq);        onInputEvent(event, displayId);    }

WindowInputEventReceiver的onInputEvent调用

ViewRootImpl的enqueueInputEvent -->doProcessInputEvents-->deliverInputEvent

在deliverInputEvent方法内进行 InputStage的链式调用如下

//WindowInputEventReceiver 继承于 InputEventReceiverfinal class WindowInputEventReceiver extends InputEventReceiver {    public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {        super(inputChannel, looper);    }    @Override    public void onInputEvent(InputEvent event, int displayId) {        enqueueInputEvent(event, this, 0, true);    }}  void enqueueInputEvent(InputEvent event,           InputEventReceiver receiver, int flags, boolean processImmediately) {....        doProcessInputEvents();....          }void doProcessInputEvents() {....deliverInputEvent(q);....    }private void deliverInputEvent(QueuedInputEvent q) {             InputStage stage;        if (q.shouldSendToSynthesizer()) {            stage = mSyntheticInputStage;        } else {            stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;        }        if (q.mEvent instanceof KeyEvent) {            mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);        }        if (stage != null) {            handleWindowFocusChanged();            //InputStage 进行链式调用//层层过滤,如果不处理交则给下一个(FORWARD),处理则返回FINISH_HANDLEstage.deliver(q);        } else {            finishInputEvent(q);        }}

InputStage 

InputStage 说明
NativePreImeInputStage 分发早于IME的InputEvent到NativeActivity中去处理, NativeActivity和普通acitivty的功能一致,不过是在native层实现,这样执行效率会更高,同时NativeActivity在游戏开发中很实用(不支持触摸事件)。
ViewPreIMEInputStage 分发早于IME的InputEvent到View框架处理,会调用view(输入焦点)的onkeyPreIme方法,同时会给View在输入法处理key事件之前先得到消息并优先处理,View系列控件可以直接复写onKeyPreIme( 不支持触摸事件)。
ImeInputStage 分发InputEvent到IME处理调用ImeInputStage的onProcess,InputMethodManager的dispatchInputEvent方法处理消息(不支持触摸事件)。
EarlyPostImeInputStage 与touchmode相关,比如你的手机有方向键,按方向键会退出touchmode,这个事件被消费,有可能会有view的背景变化,但不确定(支持触摸事件)。
NativePostImeInputStage 分发InputEvent事件到NativeActivity,IME处理完消息后能先于普通Activity处理消息(此时支持触摸事件)。
ViewPostImeInputStage 分发InputEvent事件到View框架,view的事件分发(支持触摸事件)。最终会调用到输入焦点的3个方法:使用setKeyListener注册的监听器的onKey,之后是onKeyDown和onKeyUp,或者调用activity的onKeyDown和onKeyUp方法,也就是兜底处理无人处理的key事件
SyntheticInputStage 未处理 InputEvent最后处理。

ViewPostImeInputStage是将InputEvent分发到View层的实现所在 onProcess 方法如下

  final class ViewPostImeInputStage extends InputStage {         .......        @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);                }            }        }......} private int processPointerEvent(QueuedInputEvent q) {         //..... //调用View层分发  这里的mView 为            boolean handled = mView.dispatchPointerEvent(event);          .....            return handled ? FINISH_HANDLED : FORWARD;        }

processPointerEvent 调用了mView层的dispatchPointerEvent分发, 这里的mView 为DecorView

DecorView 的dispatch方法会先调用Window.CallBack 或者KeyEvent.CallBack在进行View层的分发,

这里的Widow.CallBack的实现有Activity, Dialog等 先回调 Window.CallBack如果 返回false不处理则进行View层分发

Android Input事件APP端流程分析_第2张图片

DecorView.java    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        final Window.Callback cb = mWindow.getCallback();        return cb != null && !mWindow.isDestroyed() && mFeatureId < 0                ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);    }

此后就是我们熟悉的View或ViewGroup的dispatchTouchEvent相关流程了

例如 ViewGroup判断 point的X,Y在那个子控件内,命中子控件后,再调用子控件的dispatchTouchEvent

如果命中的子控件不处理(比如setClickable(false)),或没有命中 则调用自身的dispatchTouchEvent

 

 

更多相关文章

  1. 安卓的下拉控件Spinner
  2. android 获取路径目录方法 以及 获取路径方法
  3. Linux系统下安装android sdk的方法步骤
  4. 选项卡使用方法二(Android学习随笔十三)
  5. 使用AndroidStudio编译NDK的方法及错误解决方式
  6. Android Studio 配置快捷方式生成JNI头文件的方法
  7. android 读取DDMS里的文件时打不开,解决方法
  8. android noTouch 事件
  9. android的触摸屏事件

随机推荐

  1. 通过Linux Shell实现Android横竖屏切换
  2. ANDROID 中handler类的使用
  3. CountDownTimer浅析
  4. android 7.0平台客制化虚拟导航按键(隐藏
  5. 修改Android(安卓)Studio的Android(安卓)
  6. Unity开发备忘录000011:Unity发布Android
  7. android-gradle-plugin3.0.1源码分析
  8. Android(安卓)tesseract-orc之扫描身份证
  9. 【读书笔记】Android(安卓)输入系统
  10. Android设备通过USB线连接PC进行Socket通