android方向触摸事件,android 触摸事件最后到底传给了谁

android 触摸事件最后到底传给了谁

这个问题的答案不能靠猜,我们要从源码里去找下答案。

那首先就要说下Activity是如何显示到界面上的。

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

5066 if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {

5067 mWindow.setSoftInputMode(info.softInputMode);

5068 }

5069 if (info.uiOptions != 0) {

5070 mWindow.setUiOptions(info.uiOptions);

5071 }

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并没有把自己显示到界面上。(IOC控制反转)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 }

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

ViewRootImpl是view的顶层类,其实不是View派生类,它是view和WindowManger之间的协议转换类,触摸事件分发,绘制事件分发等。

那么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的事件分发也放出来吧!!!

@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处理了事件--cb.dispatchTouchEvent(ev);

DecorView的父类处理了触摸事件--super.dispatchTouchEvent(ev);

CallBack处理在前,DecorView父类处理在后。

好吧看来是Activity先处理事件呢,为啥是Activity呢?

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

这样我们就可以下结论了:

一、Activity对象先处理触摸事件,假设没有消耗事件。

二、DecorView拿到事件然后处理事件,假设也没有消耗事件。

三、事件返回到ViewRootImpl中,ViewRootImpl发现并没有人消耗事件,所以执行了事件的销毁方法finishInputEvent(q, false);

四、所以最后事件是传递到了ViewRootImpl中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值