View事件分发源头分析

网上有很多文章分析dispatchTouchEvent,onTouch,onTouchEvent这三个事件分发的流程,很少看到对事件源头分发的分析。简单分析下事件源头的分发。
先看对触摸消息的分发。
当屏幕收到触摸消息,系统会把触摸消息分发给Activity的DecorView的dispatchTouchEvent,

public class PhoneWindow extends Window implements MenuBuilder.Callback {
   //DecorView是PhoneWindow的内部类
   private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
    @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
          final Callback cb = getCallback();//Callback就是Activity
          return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
                    : super.dispatchTouchEvent(ev);
        }
  }
}

上面的Callback就是Activity,Activity实现了Window.Callback这个接口。
可以看到如果Callback不为空,就将消息分发给Activity,否则调用super.dispatchTouchEvent(ev),因为DecorView是个FrameLayout,于是可以走一般的ViewGroup流程,但是这里Callback一般不为空,于是消息给了Activity的dispatchTouchEvent。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();//这个方法是空的
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);//ViewGroup不消耗事件,调用onTouchEvent
    }
}

因为onUserInteraction方法是空的,走到下面getWindow().superDispatchTouchEvent(ev)。
getWindow()就是PhoneWindow,

public class PhoneWindow extends Window implements MenuBuilder.Callback {
   @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }
    
        private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { 
       public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
        }
       }
}

上面的传递,最终调用到decorView的super.dispatchTouchEvent,就是熟悉的ViewGroup的dispatchTouchEvent方法。

总结上面的流程:
1、消息先传递到DecorView
2、因为Callback不为空,DecorView将消息传递给了Activity
3、在Activity的dispatchTouchEvent里,先把消息给依DecorView为根的ViewGroup,如果ViewGroup不消耗事件,则调用Activity的onTouchEvent。

硬件 -> ViewRootImpl -> DecorView -> PhoneWindow -> Activity。

在第一步中是谁将消息传递给DecorView的呢?答案是ViewRoot。ViewRootImpl是ViewRoot的实现类,里面有个成员变量mView,这个就是DecorView。

你可能感兴趣的:(View事件分发源头分析)