Activity touch事件传递流程分析

一 编写测试代码,debug查看帧栈信息
测试代码:

View v = ViewUtil.findView(this, R.id.bt1);

v.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
在这里插入图片描述
在这里插入图片描述
ZygoteInit是用来初始化当前App进程,不用关心。Method是用来反射获取ActivityThread,而进程中所有对Activity的操作都是调用ActivityThread中的相关方法。Looper#loop是在ActivityThread的main方法中被调用,于是Looper便加入无限循环地获取Message。ActivityThread和Looper会一直运行到App进程退出才停止。这些都不是本文所关心的,继续往上看。

在Looper循环获取Message时,调用了MessageQueue#nativePollOnce方法。这个native方法又调用了InputEventReceiver#dispathInputEvent方法,从这里framework层便开始了touch事件的传递。

从以上的帧栈信息,可知touch事件传递的大概流程:感应器元件接收信息,然后通过底层驱动传递给系统服务。InputEventReceiver与系统服务相关联,于是系统服务将touch事件传递给ViewRootImpl。ViewRootImpl接收到事件后,又传递给PhoneWindow的内部类DecorView。DecorView又传递给Activity,Activity将事件传递给PhoneWindow。PhoneWindow将事件分发给DecorView,DecorView于是又分发给自己的子View。子View又继续分发,直到事件被处理。

二 主要的类和方法介绍
1 ViewRootImpl相关介绍
关于nativePollOnce如何调用InputEventReceiver#dispathInputEvent方法请阅读这篇博客:事件处理系统。
查看InputEventReceiver的源码,这是一个抽象类。它是哪个类的实例呢?不着急,点击Frames的dispatchInputEvent:185,InputEventReceiver(android.view)这一行,进入查看Variables,显示信息如下:

原来它是ViewRootImpl的内部类WindowInputEventReceiver。于是这对象调用了自己的onInputEvent方法将touch事件通过调用ViewRootImpl#enqueueInputEvent方法传递给了ViewRootImpl。于是Touch事件进入了ViewRootImpl。

看看InputEventReceiver#dispathInputEvent代码:

// Map from InputEvent sequence numbers to dispatcher sequence numbers.
private final SparseIntArray mSeqMap = new SparseIntArray();

// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
    mSeqMap.put(event.getSequenceNumber(), seq);
    onInputEvent(event);
}

1
2
3
4
5
6
7
8
9
WindowInputEventReceiver代码:

final class WindowInputEventReceiver extends InputEventReceiver {
    public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
        super(inputChannel, looper);
    }

    @Override
    public void onInputEvent(InputEvent event) {
        //ViewRootImpl的方法
        enqueueInputEvent(event, this, 0, true);
    }

    @Override
    public void onBatchedInputEventPending() {
        if (mUnbufferedInputDispatch) {
            super.onBatchedInputEventPending();
        } else {
            //ViewRootImpl的方法
            scheduleConsumeBatchedInput();
        }
    }

    @Override
    public void dispose() {
        //ViewRootImpl的方法
        unscheduleConsumeBatchedInput();
        super.dispose();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ViewRootImpl内部对事件做了一系列的处理,最后判断该事件不是键盘输入事件传递出去了。
内部类ViewPostImeInputStage的onProcess方法来执行事件类别判断,代码如下:

    @Override
    protected int onProcess(QueuedInputEvent q) {
        if (q.mEvent instanceof KeyEvent) {
            return processKeyEvent(q);
        } else {
            final int source = q.mEvent.getSource();
            if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                return processPointerEvent(q);
            } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                return processTrackballEvent(q);
            } else {
                return processGenericMotionEvent(q);
            }
        }
    }

    private int processPointerEvent(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent)q.mEvent;

        mAttachInfo.mUnbufferedDispatchRequested = false;
        final View eventTarget =
                (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?mCapturingView : mView;
        mAttachInfo.mHandlingPointerEvent = true;
        boolean handled = eventTarget.dispatchPointerEvent(event);
        maybeUpdatePointerIcon(event);
        mAttachInfo.mHandlingPointerEvent = false;
        if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
            mUnbufferedInputDispatch = true;
            if (mConsumeBatchedInputScheduled) {
                scheduleConsumeBatchedInputImmediately();
            }
        }
        return handled ? FINISH_HANDLED : FORWARD;
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
再看看mCapturingView和mView代码上的注释。

View mView;

// The view which captures mouse input, or null when no one is capturing.
//获取鼠标输入相关的视图
View mCapturingView;
1
2
3
4
5
所以在processPointerEvent方法中事件被mView分发了。

而mView通过调用ViewRootImpl#setView方法设置的。代码如下:

/**
 * We have one child
 */
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            ...//省略部分代码
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
这个View只能被设置一次,也就是说它就是Activity的根View。这个根View传递给DecorView。这个mView是哪种类型的View呢?继续查看帧栈中的变量信息。点击dispatchPoninterEvent:8799,View(android.view)这一行,查看Variables中显示的信息。如下图所示:

它是DecorView的实例,也就是说DecorView的对象是当前Activity中最顶级的View,其它的View都是他的子孙View,状态栏和底部的导航栏都是在DecorView或其子孙View的内部。

插个小话题,讲讲ViewRootImpl创建和setView的调用
而ViewRootImpl是何时创建,mView(DecorView对象)又是何时被setView方法添加到ViewRootImpl?这个mView(DecorView对象)既然是根View,可以猜测管理它的对象一定是WindowManagerGlobal的。WindowManagerGlobal是管理Android中所有根View的超级大管家,而且也只管理根View。

先看看WindowManagerGlobal中相关的代码:

//记录根View
private final ArrayList<View> mViews = new ArrayList<View>();
//记录ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
//记录WindowManager.LayoutParams
private final ArrayList<WindowManager.LayoutParams> mParams =
        new ArrayList<WindowManager.LayoutParams>();

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ...//省略部分代码

    //ViewRootImpl出现
    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {
        ...//

        //创建ViewRootImpl对象
        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);

        //记录信息,方便管理,页面重新显示和移除时可以从中查找。
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
    }

    // do this last because it fires off messages to start doing things
    try {//将根View设置到ViewRootImpl,便能从ViewRootImpl传递事件给View
        root.setView(view, wparams, panelParentView);
    } catch (RuntimeException e) {
        // BadTokenException or InvalidDisplayException, clean up.
        synchronized (mLock) {
            final int index = findViewLocked(view, false);
            if (index >= 0) {
                removeViewLocked(index, true);
            }
        }
        throw e;
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
WindowManagerImpl调用WindowManagerGlobal的相关代码:

public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

...//省略部分代码
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
...//省略部分代码

}
1
2
3
4
5
6
7
8
9
10
11
ActivityThread#handleResumeActivity方法中调用了WindowManger来添加DecorView。

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    …//省略代码
    if (r != null) {
        final Activity a = r.activity;

        …//省略代码

        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            //获取DecorView
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            //WindowManager为接口,实际为WindowMangerImpl对象
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;

            ...//省略部分代码

            if (a.mVisibleFromClient && !a.mWindowAdded) {
                a.mWindowAdded = true;
                //添加到WindowMangerGoble
                wm.addView(decor, l);
            }

        ...//省略代码

    } else {
        ...//
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2 PhoneWindow和DecorView相关介绍
继续看touch事件传递。刚才分析到ViewRootImpl的子类ViewPostImeInputStage
在processPointerEvent方法中将事件传递给了DecorView的dispatchTouchEvent。
继续看DecorView的dispatchTouchEvent方法代码:

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

1
2
3
4
5
6
调用的是PhoneWindow#getCallback来获取,即Window的getCallback方法。这个mCallback其实就是当前Activity。Activity也实现了Window.Callback接口,用来接收窗口的事件。
Window的getCallback方法代码:

public final Callback getCallback() {
return mCallback;
}
1
2
3
在Activity#attach方法内,创建了PhoneWindow,并将自己设置给PhoneWindow。
Activity#attach方法代码:

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) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);
    //创建PhoneWindow
    mWindow = new PhoneWindow(this, window);
    mWindow.setWindowControllerCallback(this);
    //将Activity自己设置给PhoneWindow
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    ...//省略
    //设置WindowManagerImpl
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    ...//省略
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Window中setWindowManager代码:

public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) {
    mAppToken = appToken;
    mAppName = appName;
    mHardwareAccelerated = hardwareAccelerated
            || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
    if (wm == null) {
        wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}

1
2
3
4
5
6
7
8
9
10
3 Activity相关介绍
touch事件终于传递到Activity了。咦,Activity怎么没有传递给内部的View,居然传递给PhoneWindow。
Activity#dispatchTouchEvent代码:

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    //传递给PhoneWindow
    if (getWindow().superDispatchTouchEvent(ev)) {
   //如果事件被处理,则返回true
        return true;
    }
    return onTouchEvent(ev);
}

1
2
3
4
5
6
7
8
9
10
11
PhoneWindow#superDispatchTouchEvent代码:

@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
    //将事件传递给DecorView
    return mDecor.superDispatchTouchEvent(event);
}

1
2
3
4
5
DecorView的superDispatchTouchEvent代码:

public boolean superDispatchTouchEvent(MotionEvent event) {
    return super.dispatchTouchEvent(event);
}

1
2
3
因为DecorView继承了FrameLayout,super.dispatchTouchEvent也调用了ViewGroup的dispatchTouchEvent和diaptchTransformedTouchEvent方法来继续对子View进行touch事件分发,直至事件被处理。关于ViewGroup和View如何分发和处理touch事件,请阅读博客:Android触摸屏事件派发机制详解与源码分析一(View篇)和Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇) 。

于是事件传递到断点所在的代码行,整个touch事件传递个过程分析完毕。

4 类图
图中画的是这篇文章中所涉及到的类,画了主要的属性和方法。
在这里插入图片描述
注:如果是Android 6.0或以上代码,DecorView已从PhoneWindow中抽出,成独立的一个类。

补充:如果不想用断点,也可以在onTouch方法中使用Thread.dumpStack();以日志的方式将帧栈中的信息打印出来,慢慢分析。

dump的stack信息:

java.lang.Throwable: stack dump
at java.lang.Thread.dumpStack(Thread.java:490)
at test.TestMainActivity 1. o n T o u c h ( T e s t M a i n A c t i v i t y . j a v a : 32 ) a t a n d r o i d . v i e w . V i e w . d i s p a t c h T o u c h E v e n t ( V i e w . j a v a : 8582 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T r a n s f o r m e d T o u c h E v e n t ( V i e w G r o u p . j a v a : 2519 ) a t a n d r o i d . v i e w . V i e w G r o u p . d i s p a t c h T o u c h E v e n t ( V i e w G r o u p . j a v a : 2171 ) a t c o m . a n d r o i d . i n t e r n a l . p o l i c y . i m p l . P h o n e W i n d o w 1.onTouch(TestMainActivity.java:32) at android.view.View.dispatchTouchEvent(View.java:8582) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171) at com.android.internal.policy.impl.PhoneWindow 1.onTouch(TestMainActivity.java:32)atandroid.view.View.dispatchTouchEvent(View.java:8582)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atandroid.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2519)atandroid.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2171)atcom.android.internal.policy.impl.PhoneWindowDecorView.superDispatchTouchEvent(PhoneWindow.java:2482)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1798)
at android.app.Activity.dispatchTouchEvent(Activity.java:2827)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:67)
at com.android.internal.policy.impl.PhoneWindow D e c o r V i e w . d i s p a t c h T o u c h E v e n t ( P h o n e W i n d o w . j a v a : 2443 ) a t a n d r o i d . v i e w . V i e w . d i s p a t c h P o i n t e r E v e n t ( V i e w . j a v a : 8799 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l DecorView.dispatchTouchEvent(PhoneWindow.java:2443) at android.view.View.dispatchPointerEvent(View.java:8799) at android.view.ViewRootImpl DecorView.dispatchTouchEvent(PhoneWindow.java:2443)atandroid.view.View.dispatchPointerEvent(View.java:8799)atandroid.view.ViewRootImplViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4706)
at android.view.ViewRootImpl V i e w P o s t I m e I n p u t S t a g e . o n P r o c e s s ( V i e w R o o t I m p l . j a v a : 4537 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l ViewPostImeInputStage.onProcess(ViewRootImpl.java:4537) at android.view.ViewRootImpl ViewPostImeInputStage.onProcess(ViewRootImpl.java:4537)atandroid.view.ViewRootImplInputStage.deliver(ViewRootImpl.java:4051)
at android.view.ViewRootImpl I n p u t S t a g e . o n D e l i v e r T o N e x t ( V i e w R o o t I m p l . j a v a : 4104 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l InputStage.onDeliverToNext(ViewRootImpl.java:4104) at android.view.ViewRootImpl InputStage.onDeliverToNext(ViewRootImpl.java:4104)atandroid.view.ViewRootImplInputStage.forward(ViewRootImpl.java:4070)
at android.view.ViewRootImpl A s y n c I n p u t S t a g e . f o r w a r d ( V i e w R o o t I m p l . j a v a : 4207 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l AsyncInputStage.forward(ViewRootImpl.java:4207) at android.view.ViewRootImpl AsyncInputStage.forward(ViewRootImpl.java:4207)atandroid.view.ViewRootImplInputStage.apply(ViewRootImpl.java:4078)
at android.view.ViewRootImpl A s y n c I n p u t S t a g e . a p p l y ( V i e w R o o t I m p l . j a v a : 4264 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l AsyncInputStage.apply(ViewRootImpl.java:4264) at android.view.ViewRootImpl AsyncInputStage.apply(ViewRootImpl.java:4264)atandroid.view.ViewRootImplInputStage.deliver(ViewRootImpl.java:4051)
at android.view.ViewRootImpl I n p u t S t a g e . o n D e l i v e r T o N e x t ( V i e w R o o t I m p l . j a v a : 4104 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l InputStage.onDeliverToNext(ViewRootImpl.java:4104) at android.view.ViewRootImpl InputStage.onDeliverToNext(ViewRootImpl.java:4104)atandroid.view.ViewRootImplInputStage.forward(ViewRootImpl.java:4070)
at android.view.ViewRootImpl I n p u t S t a g e . a p p l y ( V i e w R o o t I m p l . j a v a : 4078 ) a t a n d r o i d . v i e w . V i e w R o o t I m p l InputStage.apply(ViewRootImpl.java:4078) at android.view.ViewRootImpl InputStage.apply(ViewRootImpl.java:4078)atandroid.view.ViewRootImplInputStage.deliver(ViewRootImpl.java:4051)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6507)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6481)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6434)
at android.view.ViewRootImpl W i n d o w I n p u t E v e n t R e c e i v e r . o n I n p u t E v e n t ( V i e w R o o t I m p l . j a v a : 6666 ) a t a n d r o i d . v i e w . I n p u t E v e n t R e c e i v e r . d i s p a t c h I n p u t E v e n t ( I n p u t E v e n t R e c e i v e r . j a v a : 185 ) a t a n d r o i d . o s . M e s s a g e Q u e u e . n a t i v e P o l l O n c e ( N a t i v e M e t h o d ) a t a n d r o i d . o s . M e s s a g e Q u e u e . n e x t ( M e s s a g e Q u e u e . j a v a : 148 ) a t a n d r o i d . o s . L o o p e r . l o o p ( L o o p e r . j a v a : 151 ) a t a n d r o i d . a p p . A c t i v i t y T h r e a d . m a i n ( A c t i v i t y T h r e a d . j a v a : 5759 ) a t j a v a . l a n g . r e f l e c t . M e t h o d . i n v o k e ( N a t i v e M e t h o d ) a t j a v a . l a n g . r e f l e c t . M e t h o d . i n v o k e ( M e t h o d . j a v a : 372 ) a t c o m . a n d r o i d . i n t e r n a l . o s . Z y g o t e I n i t WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6666) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:148) at android.os.Looper.loop(Looper.java:151) at android.app.ActivityThread.main(ActivityThread.java:5759) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6666)atandroid.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)atandroid.os.MessageQueue.nativePollOnce(NativeMethod)atandroid.os.MessageQueue.next(MessageQueue.java:148)atandroid.os.Looper.loop(Looper.java:151)atandroid.app.ActivityThread.main(ActivityThread.java:5759)atjava.lang.reflect.Method.invoke(NativeMethod)atjava.lang.reflect.Method.invoke(Method.java:372)atcom.android.internal.os.ZygoteInitMethodAndArgsCaller.run(ZygoteInit.java:1042)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:837)

本文参考的博客:
【Android】事件处理系统
http://www.cnblogs.com/lcw/p/3373214.html

Touch事件如何传递到Activity
http://www.jianshu.com/p/7d442ed0a355

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值