美文网首页
Activity分发源码分析

Activity分发源码分析

作者: Utte | 来源:发表于2018-07-28 09:09 被阅读20次

    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,分发完成。

    相关文章

      网友评论

          本文标题:Activity分发源码分析

          本文链接:https://www.haomeiwen.com/subject/ugjimftx.html