这里的window可以理解为PhoneWindow,事件分发在Activity、DecorView、PhoneWindow中的顺序。
当屏幕被触摸,首先会通过硬件产生触摸事件传入内核,然后走到FrameWork层,最后经过一系列事件处理到达ViewRootImpl的processPointerEvent方法,接下来就是我们要分析的内容了:
//ViewRootImpl.java
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
...
//mView分发Touch事件,mView就是DecorView
boolean handled = mView.dispatchPointerEvent(event);
...
}
//DecorView.java
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
//分发Touch事件
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//cb其实就是对应的Activity
final Window.Callback cb = mWindow.getCallback();
return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
}
//Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
//PhoneWindow.java
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}
//DecorView.java
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
我们来看一下 上文中 Window.Callback cb = mWindow.getCallback()
cb其实就是对应的Activity
在Activity的attach方法中,创建了PhoneWindow,并且设置了callback,windowManager。
final void attach() {
//初始化PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
//和WindowManager关联
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
}
事件的分发流程就比较清楚了:
ViewRootImpl——>DecorView——>Activity——>PhoneWindow——>DecorView——>ViewGroup
(这其中就用到了getCallback参数,也就是之前addView中传入的callback,也就是Activity本身)
但是这个流程确实有些奇怪,为什么绕来绕去的呢,光DecorView就走了两遍。
主要原因就是解耦。
ViewRootImpl并不知道有Activity这种东西存在,它只是持有了DecorView。所以先传给了DecorView,而DecorView知道有AC,所以传给了AC。
Activity也不知道有DecorView,它只是持有PhoneWindow,所以这么一段调用链就形成了。