Android事件传递

1. 在Activity的启动过程中,窗口和视图创建完后, 会创建输入通道InPutChannel, 该类执行了Parceladble,专门用来传输用户输入事件给window.

2. 用InPutChannel和主线程的Looper作为参数创建事件接收器WindowInputEventReceiver.

    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,Looper.myLooper()); 
    WindowInputEventReceiver继承InputEventReceiver,是ViewRootImpl的内部类.

3. 当native层的输入管理器监听到输入事件后调用InputEventReceiver.dispatchInputEvent()方法,该方法再通过以下调用链最终进入DecorView.dispatchKeyEvent()方法执行.

    WindowInputEventReceiver.onInputEvent()—>enqueueInputEvent()—>doProcessInputEvents()—>deliverInputEvent()—>deliver()—>

    ViewPostImeInputStage.onProcess()—>ViewPostImeInputStage.processKeyEvent()—>DecorView.dispatchKeyEvent()

4. DecorView.dispatchKeyEvent()方法有两个分支:

  1) 在窗口被销毁的时候,比如息屏状态下调整音量,则直接调用PhoneWindow.onKeyDown()方法,并在该方法中处理音量的调节.

  2) 在窗口没有被销毁的时候,调用Activity.dispatchKeyEvent()方法进行事件分发.

        public boolean dispatchKeyEvent(KeyEvent event) {
            final int keyCode = event.getKeyCode();
            final int action = event.getAction();
            final boolean isDown = action == KeyEvent.ACTION_DOWN;

            ...

            if (!isDestroyed()) {                                            //窗口没有销毁的情况
                final Callback cb = getCallback();
                final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) //这个Callback是在activity的attach()方法里面设置到window中的。
                        : super.dispatchKeyEvent(event);
                if (handled) {
                    return true;
                }
            }

            return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)   //窗口销毁后直接调用PhoneWindow的onkeyDown()方法处理。
                    : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
        }
5. Activity通过PhoneWindow将事件传递给view系统
    public boolean dispatchKeyEvent(KeyEvent event) {
        onUserInteraction();

        // Let action bars open menus in response to the menu key prioritized over
        // the window handling it
        if (event.getKeyCode() == KeyEvent.KEYCODE_MENU &&       //按的menu键,则直接调用mActionBar.onMenuKeyEvent(event),并返回true,事件不再向下传递。
                mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
            return true;
        }

        Window win = getWindow();
        if (win.superDispatchKeyEvent(event)) {              //通过PhoneWindow调用view和viewgrounp的Dispatch方法传递事件,如果该事件被某个view或者viewgrounp处理,
                                                                                         // 返回true,到此结束,否则继续向下传递。
            return true;
        }
        View decor = mDecor;
        if (decor == null) decor = win.getDecorView();
        return event.dispatch(this, decor != null
                ? decor.getKeyDispatcherState() : null, this);              //如果该事件没有被view或者viewgrounp处理,则直接调用event.dispatch(),
                                                                                                         //在该方法里面调用activiy的onkeydown()方法处理。
    }
6. view系统将事件从根view开始向子view传递,如果事件被某个view或者viewGrounp消费,则停止向下传递,否则最终将调用Activity的onKeyDown()方法进行处理.

    以textView为例,事件在view系统的传递路径为:

    DecorView.superDispatchKeyEvent()—>viewgrounp.dispatchKeyEvent()—>view.dispatchKeyEvent()—>KeyEvent.dispatch()—>TextView.onKeyDown()

  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值