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);