android(五)、 ViewRoot触摸事件流程

本文主要内容:

       ViewRoot是为WindowManagerGlobal而设计的,它承担了View和WindowManger沟通的角色,属于View顶层设计。ViewRoot的工作包括但不限于-触摸事件分发,view树的绘制事件分发,测绘事件的分发,布局事件的分发。

第一、ViewRoot的触摸事件分发


   准备工作:那首先就要说下Activity是如何通过ViewRoot显示到界面上的。

    Activity的attach()大致干了三件事:

1、创建Window对象(PhoneWindow)

2、为window对象设置CallBack回调对象,非常重要

3、为window对象设置WindowManger管理者,WindowManager对象是在ContextImpl类第一次被加载进时创建的(静态域),实际为WindowManagerImpl对象。

Activity的attach()方法体如下:

5053    final void attach(Context context, ActivityThread aThread,
5054            Instrumentation instr, IBinder token, int ident,
5055            Application application, Intent intent, ActivityInfo info,
5056            CharSequence title, Activity parent, String id,
5057            NonConfigurationInstances lastNonConfigurationInstances,
5058            Configuration config) {
5059        attachBaseContext(context);
5060
5061        mFragments.attachActivity(this, mContainer, null);
5062        
5063        mWindow = PolicyManager.makeNewWindow(this);
5064        mWindow.setCallback(this);
5065        mWindow.getLayoutInflater().setPrivateFactory(this);
5072        mUiThread = Thread.currentThread();
5085        mLastNonConfigurationInstances = lastNonConfigurationInstances;
5086
5087        mWindow.setWindowManager(
5088                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
5089                mToken, mComponent.flattenToString(),
5090                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
5091        if (mParent != null) {
5092            mWindow.setContainer(mParent.getWindow());
5093        }
5094        mWindowManager = mWindow.getWindowManager();
5095        mCurrentConfig = config;
5096    }

Activity显示工作:

      上述过程明显Activity并没有把自己显示到界面上。Activity实际上并不控制自己的显示,由它的控制引擎(framework框架)来管理。

      Activity的显示实际工作是ActivityThread完成的,在ActivityThread的handleResumeActivity方法中核心代码如下:

2796                r.window = r.activity.getWindow();
2797                View decor = r.window.getDecorView();
2798                decor.setVisibility(View.INVISIBLE);
2799                ViewManager wm = a.getWindowManager();
2800                WindowManager.LayoutParams l = r.window.getAttributes();
2801                a.mDecor = decor;
2802                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2803                l.softInputMode |= forwardBit;
2804                if (a.mVisibleFromClient) {
2805                    a.mWindowAdded = true;
2806                    wm.addView(decor, l);
2807                }

完成的主要工作如下(完成Activity的显示工作):

1、获取Activity中的window对象。

2、获取Activity中的DecorView。

3、获取Activity中的WindowManger对象,a为r.activity。

4、将DecorView添加到WindowMangerImpl中。

5、WindowManagerImpl添加DecorView对象,添加过程中又用ViewRootImpl包装了一下。


ViewRootImpl分发事件

那么ViewRootImpl是如何分发事件的,由于方法体较长,所以删除了一部分留下了我们比较关注的主题部分:

 private void deliverPointerEvent(QueuedInputEvent q) {
3178        final MotionEvent event = (MotionEvent)q.mEvent;
3179        final boolean isTouchEvent = event.isTouchEvent();
3219        // Dispatch touch to view hierarchy.
3220        boolean handled = mView.dispatchPointerEvent(event);
3221        if (MEASURE_LATENCY) {
3222            lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());
3223        }
3224        if (handled) {
3225            finishInputEvent(q, true);
3226            return;
3227        }
3228
3229        // Pointer event was unhandled.
3230        finishInputEvent(q, false);
3231    }
3232

首先会不停的从触摸消息的消息队列中取出消息体,然后事件给了DecorView对象,那么把DecorView的事件分发方法体也放出来吧!!!

  • CallBack处理了事件--cb.dispatchTouchEvent();
  • DecorView的父类处理了触摸事件--super.dispatchTouchEvent();
  • CallBack处理在前,DecorView父类处理在后。

 @Override
1899        public boolean More ...dispatchTouchEvent(MotionEvent ev) {
1900            final Callback cb = getCallback();
1901            return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
1902                    : super.dispatchTouchEvent(ev);
1903        }
1904


     此处CallBack为Activity,因为Activity的attch方法把自身作为callBack对象传给了Window对象,这里的getCallBack方法就是获取WIndow的CallBack对象。


Activity中

      一、Activity会首先处理事件。

      二、DecorView为第二个处理事件的。

      三、假设事件没有消耗,那么事件将返回到ViewRootImpl中,ViewRootImpl发现并没有View消耗事件,便执行了事件的销毁方法finishInputEvent(q, false);

非Activity

      一、DecorView为第一个处理事件的。

      二、假设事件没有消耗,那么事件将返回到ViewRootImpl中,ViewRootImpl发现并没有View消耗事件,便执行了事件的销毁方法finishInputEvent(q, false);


猜你喜欢

转载自blog.csdn.net/jiabailong/article/details/51917495