那天有人问我,Android 的事件到底是怎么来的?

作者:酱爆大头菜

链接:

https://www.jianshu.com/p/470beda7ee64

本文主要针对的是 我们认为的事件分发 之前的流程,也就是说事件是怎么来的?一路又是怎么走下去的?

那为什么要研究事件的来龙去脉呢?其实我写本文之前是知道事件是以下的这种走向传递的。

Avtivity->PhoneWindow->DecorView->ViewGroup->View

直到有一天,有人问我那Activity是怎么接到事件的?我当时是一脸懵逼,然后就没有然后了,所以至于是谁问的我,估计你们也知道了。

本文争取以极简的方式来描述,如有问题欢迎指正。

我们开始表演

首先整个过程中会涉及以下几个类

  1. Activity
  2. PhoneWindow extends Window
  3. WindowManager extends ViewManager
  4. WindowManagerImpl implements WindowManager
  5. WindowManagerGlobal
  6. ViewRootImpl implements ViewParent
  7. WindowManagerService extends IWindowManager.Stub
  8. DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks
  9. InputChannel,InputQueue,WindowInputEventReceiver extends InputEventReceiver
  10. ViewRootHandler extends Handler

OK,我们先上结论,后展开说明,以下部分纯干货,如之前看过部分源码可直接看这部分,对源码不是很熟悉的也没有关系,下一个环节就是展开说明。

先上张图理解一下,图片内容较多,可点击原图欣赏无码大图 。

1. ActivityThread.performLaunchActivity() 中调用 Activity.attach(),创建PhoneWindow,PhoneWindow创建DecorView。

2. ActivityThread.handleResumeActivity()中调用Activity.makeVisible(),初始化WindowManager并调用WindowManager.addView()

3. 因为WindowManager是接口,找到其实现类并调用WindowManagerImpl.addView()。

4. 调用WindowManagerGlobal.addView(View view, ..., Window parentWindow, ...)

此时需要注意view为DecorView对象,该对象是通过ActivityThread.handleResumeActivity()中的PhoneWindow.getDecorView()获取,并直接赋值给Activity变量的。

5. WindowManagerGlobal.addView()创建了ViewRootImpl,并调用了ViewRootImpl.setView(view,...,...)

6. 连带创建InputChannel,InputQueue以及WindowInputEventReceiver对象并传入InputChannel和Looper

7. 其实Android事件的源头来自于用户输入行为,由硬件进行捕获,一般会保存在dev/input节点下,后续组装成KeyEvent/MotionEvent对象,经Native进入Java的InputEventReceiver.dispatchInputEvent()中。

8. ViewRootImpl.WindowInputEventReceiver extends InputEventReceiver,连带调用了enqueueInputEvent()->doProcessInputEvents-> deliverInputEvent(q),方法中获取到mFirstPostImeInputStage对象其实为ViewPostImeInputStage。

9. ViewPostImeInputStage extends InputStage 因此执行onProcess(),判断如果是触摸事件,调用processPointerEvent(),然后内部调用mView.dispatchPointerEvent(),此时的mView为DecorView,辗转调用到了DecorView.dispatchTouchEvent()

10. 通过 mWindow.getCallback()获取Window.Callback然后调用Window.Callback.dispatchTouchEvent(),这个Callback就是PhoneWindow里的mCallback,而mCallback则是Activity的attach()赋值的,此处也就自然调用到了Activity中,后续就是我们都知道的事件分发了,一个完整的闭环就结束了。

ActivityThread.performLaunchActivity()

 

  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
          ...
            if (activity != null) {
               ...
              //可以看到此处调用了Activity的attach()方法
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);
            ...
            }
}

1.1 Activity.attach()中进行了PhoneWindow初始化,并设置CallBack对象。

 

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,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
        //PhoneWindow初始化
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(mWindowControllerCallback);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInfl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值