Activity分发源码分析

2018-07-28  本文已影响20人  Utte

Activity分发机制

Activity # dispatchTouchEvent(MotionEvent ev)

public boolean dispatchTouchEvent(MotionEvent ev) {
    
    // 判断是否为ACTION_DOWN事件。
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
        //此方法为空实现,当此activity在栈顶时,触屏点击按home,back,menu键等都会触发此方法。
        // 注释说当此Activity运行时,如果你想知道用户与此有交互,就实现此方法。
        // public void onUserInteraction() {
        // }
    }
    
    if (getWindow().superDispatchTouchEvent(ev)) {
        // 获取当前Activity的Window。
        // public Window getWindow() { 
        //     return mWindow;
        // }
        
        // 调用当前Window对象的superDispatchTouchEvent(ev),Window的真正实现类是PhoneWindow,
        // 所以实际调用的是PhoneWindow的superDispatchTouchEvent(ev)。
        // PhoneWindow又调用了顶级View的superDispatchTouchEvent(event)。
        // @Override
        // public boolean superDispatchTouchEvent(MotionEvent event) {
        //     return mDecor.superDispatchTouchEvent(event);
        // }
        
        // 顶级View的父类是FrameLayout,FrameLayout的父类是ViewGroup。
        // FrameLayout没有重写dispatchTouchEvent(event),
        // 所以此处调用了ViewGroup的dispatchTouchEvent(event)。
        // 完成了从Activity到ViewGroup的事件传递,
        // 接受了ViewGroup的dispatchTouchEvent(event)的返回值,
        // 表示在向下分发的过程中,存在View消耗了此事件。
        //public boolean superDispatchTouchEvent(MotionEvent event) {
        //    return super.dispatchTouchEvent(event);
        //}
        
        return true;
        // 如果ViewGroup的dispatchTouchEvent(event)返回了true,也就是有View消耗了该事件,
        // 那么Activiy的dispatchTouchEvent()就返回true,完成了整个事件分发过程。
        // 否则继续。
    }
    
    return onTouchEvent(ev);
    // 此时代表在事件向下分发过程中没有View消耗该事件,就Activity自己消耗该事件。
    // 调用Activity的onTouchEvent(ev)。
    
}

Activity # onTouchEvent(MotionEvent event)

// Activity向下分发中没有任何View消耗该事件时被调用
// Activity本身尝试消耗
public boolean onTouchEvent(MotionEvent event) {
    if (mWindow.shouldCloseOnTouch(this, event)) {
        // 判断是否是DOWN事件,event的坐标是否在边界内等。
        // 如果是,就消耗事件返回true,否则不消耗返回false。
        // public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
        //     if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
        //             && isOutOfBounds(context, event) && peekDecorView() != null) {
        //         return true;
        //     }
        //     return false;
        // }
        finish();
        // 分发完成,结束。
        return true;
        // 返回true,事件已经被Activity消耗。
    }
    return false;
    //返回false,因为事件没有被消耗。
}

过程总结

  1. 一个点击事件开始后会调用到Activity的dispatchTouchEvent()。
  2. Activity的会将事件传递给Window的superDispatchTouchEvent(),这个方法的实现在PhoneWindow中。
  3. PhoneWindow将时间继续传递,调用了DecorView的superDispatchTouchEvent()。
  4. DecorView将事件传递给父类,调用了ViewGroup的dispatchTouchEvent(),交给ViewGroup继续向下分发。
  5. 如果向下分发过程中事件被消耗,那么Activity分发过程结束,Activity的dispatchTouchEvent()返回true。
  6. 如果没有被消耗,则调用Activity的onTouchEvent()。
  7. onTouchEvent()中判断了事件是否为ACTION_DOWN、是否在边界内等,如果是就消耗该事件,返回true,Activity的dispatchTouchEvent()也返回true,分发完成。
  8. 如果不符合判断,则Activity也不消耗,返回false,Activity的dispatchTouchEvent()返回false,分发完成。
上一篇下一篇

猜你喜欢

热点阅读