View 点击事件的传递

view的点击事件是从 WMS 传递过来,那么必须注册监听器之类到 WMS 中,

1、ViemRootImpl 中 addView 时可以看到注册了一个类似监听器的一个类,

 if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
               
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, 
                            mInputChannel);
}

这里主要是 new 了一个 InputChannel,然后通过 mWindowSession.addToDisplay 注册到 WMS 中。

2、mWindowSession.addToDisplay 逻辑可以追踪到,mWindowSesison 指向的是 com.android.server.wm.Session

 public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
            Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
                outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
    }

mService 指向的就是 WMS, addWindow 的实现如下

 public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {


......

  final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
  if  (openInputChannels) {
          win.openInputChannel(outInputChannel);
   }
......


}

openInputChanel 的实现如下

// WindowState.java
void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
        mInputChannel = inputChannels[0];
        mClientChannel = inputChannels[1];
        mInputWindowHandle.inputChannel = inputChannels[0];
        if (outInputChannel != null) {
            mClientChannel.transferTo(outInputChannel);
            mClientChannel.dispose();
            mClientChannel = null;
        } else {
            // If the window died visible, we setup a dummy input channel, so that taps
            // can still detected by input monitor channel, and we can relaunch the app.
            // Create dummy event receiver that simply reports all events as handled.
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
        }
        mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
    }

最后的 registerInputChannel 会执行到 natvie 方法。

现在注册流程已经很清楚了,那什么时候被被回调呢?,这个时候就需要去看 InputChanel 的实现了。

2、点击事件回调

  

// ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
......
if (mInputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
                }
.....
}

其中 WindowInputEventReceiver 的父类为  InputEventReceiver,其中有如下:

// InputEventReceiver.java

// Called from native code.
 @SuppressWarnings("unused")
 private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
     mSeqMap.put(event.getSequenceNumber(), seq);
      onInputEvent(event, displayId);
 }

当点击事件 来之后, natvie 层通过回调 dispachInputEvent 方法,后续会执行到下面代码

// ViewRootImpl.java
void enqueueInputEvent(InputEvent event,
            InputEventReceiver receiver, int flags, boolean processImmediately) {
.......
if (processImmediately) { // 这里为true
            doProcessInputEvents();
     } else {
            scheduleProcessInputEvents();
    }
......


}


void doProcessInputEvents() {

......
 deliverInputEvent(q);
......

}

deliverInputEvent 后面后调用到 ViewPostImeInputStage#process

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) {
            final MotionEvent event = (MotionEvent)q.mEvent;

            mAttachInfo.mUnbufferedDispatchRequested = false;
            mAttachInfo.mHandlingPointerEvent = true;
           //这里就是熟悉的 view 事件分发入口啦
            boolean handled = mView.dispatchPointerEvent(event); 
            
            return handled ? FINISH_HANDLED : FORWARD;
        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值