Android View相关-事件分发机制流程

经过前两篇的学习,相信已经对事件分发的一个流程产生了一定的理解(才怪),那么这一章我们来看看整个事件分发从Activity到被消费的过程。好了,脑袋放空,我们开始。

Activity中的View结构

我们在这里先插一嘴Activity中的View结构。在开发过程中,我们通常使用setContentView来设置Activity的视图,Android中可见页面都是附着于窗口也就是Window上的,而DecorView是Window的最顶层视图。在Android Framework层,与窗口处理有关的类,主要是Window类和其实现类PhoneWindow,DecorView则是PhoneWindow的内部类,继承了FrameLayout。

//PhoneWindow.java
public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
}

而我们调用setContentView的本质是将View添加至DecorView,可以看到Activity源码中:

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

最终是调用了Window的setContentView,我们知道Window的实现类是PhoneWindow,来看下PhoneWindow中的实现:

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,getContext());
        transitionTo(newScene);
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

可以看到在12行,将Activity的View添加到DecorView中(mContentParent是DecorView的一个子View,具体可以查看PhoneWindow的generateLayout方法)。我们可以将添加页面至窗口的流程做一个总结:

那么Activity视图被添加到Window的过程我们已经搞明白了,当然这跟本章内容弄并没有太大关系

不过多学一点东西还是有必要的,那么我们开始今天的主题,事件分发的总流程。

扫描二维码关注公众号,回复: 134279 查看本文章

事件分发流程

我们知道,事件分发最初是到达Activity,然后依次下发,大致上:

Activity ——> PhoneWindow ——> DecorView——> ViewGroup ——> … ——> View

是这样一个流程,由于我们无法操作PhoneWindow以及DecorView,下面我们就来分析一下Activity、ViewGroup、View这三者的的流程,我们先来分析这三者与事件分发有关的方法:

  • Activity:dispatchTouchEvent()、onTouchEvent()
  • ViewGroup:dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent()
  • View:dispatchTouchEvent()、onTouchEvent()

我们知道Activity中管理视图的根View是DecorView,我们先从DecorView来看:

//DecorView
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final Callback cb = getCallback();
    return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
        : super.dispatchTouchEvent(ev);
}
//Window
public final Callback getCallback() {
        return mCallback;
}

DecorView首先对mCallback进行了判断,如果mCallback不为空那么调用mCallback的dispatchTouchEvent,我们来看看mCallback是怎么进行赋值的:

//Window
public void setCallback(Callback callback) {
    mCallback = callback;
}
//Activity
final void attach(Context context, ActivityThread aThread,
                  Instrumentation instr, IBinder token, int ident,
                  Application application, Intent intent, ActivityInfo info,
                  CharSequence title, Activity parent, String id,
                  NonConfigurationInstances lastNonConfigurationInstances,
                  Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    ...
        mWindow = new PhoneWindow(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    ...
}

从上面代码可以看出DecorView的dispathcTouchEvent最终使用的,仍是Activity的dispathcTouchEvent,而我们知道,DecorView是FrameLayout的子类,也是一个ViewGroup,我们回忆一下之前的ViewGroup以及View的事件分发执行流程,就可以很轻易的得出Activity、ViewGroup、View这三者事件分发的一个流程情况:

  • View消费事件:

  • ViewGroup消费事件:

  • Activity消费事件:

Activity的整个事件分发流程就是这样了,这是一个Java当中典型的责任链模式,如果理解了这个设计模式,那么对于理解Android事件分发机制会大有帮助。关于责任链模式,可以参考博文Java模式之责任链模式

好了,以上就是本篇文章的全部内容了,如果您对文章有任何疑问或者文章内有错误或者遗漏的部分,欢迎在评论区指正,谢谢观看~

我的个人博客,欢迎访问,交流~

猜你喜欢

转载自blog.csdn.net/xiaomi987/article/details/80221173