按键分析--APP部分-- OnTouch事件处理流程
来源:互联网 发布:足球推荐软件 编辑:程序博客网 时间:2024/05/18 03:14
5.2.1 OnTouchListener注册和使用
1)子类实现View.OnTouchListener,View.OnTouchListener是view的一个接口,
public class Workspace extends SmoothPagedView
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
Insettable, OnScaleGestureListener {
…
@Override
public boolean onTouch(View v, MotionEvent event) {
}
2)向目的view注册OnTouchListener监听器,把类自身当作监听器
public void onChildViewAdded(View parent, View child) {
CellLayout cl = ((CellLayout) child);
cl.setOnInterceptTouchListener(this);
…
}
3)目的view通知监听器,
private OnTouchListener mInterceptTouchListener;
public void setOnInterceptTouchListener(View.OnTouchListener listener) {
mInterceptTouchListener = listener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
return true;
}
if (action == MotionEvent.ACTION_DOWN) { setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY());
}
return false;
}
5.2.2 OnTouchListener栈分析
在launcher里的workspace的onTouch调用栈:
Workspace.onTouch(View, MotionEvent) line: 1506 9)
CellLayout.onInterceptTouchEvent(MotionEvent) line: 904 8)
CellLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2113
Workspace(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
Workspace(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
Workspace.dispatchTouchEvent(MotionEvent) line: 8001
FrameLayout(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
AnimationDragLayer(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
AnimationDragLayer(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
DragLayer(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
DragLayer(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
FrameLayout(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
FrameLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
LinearLayout(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
LinearLayout(ViewGroup).dispatchTouchEvent(MotionEvent)line: 2202 7)
PhoneWindow$DecorView(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
PhoneWindow$DecorView(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202 6)
PhoneWindow$DecorView.superDispatchTouchEvent(MotionEvent) line: 2442
PhoneWindow.superDispatchTouchEvent(MotionEvent) line: 1751 5)
Launcher(Activity).dispatchTouchEvent(MotionEvent) line: 2828 4)
PhoneWindow$DecorView.dispatchTouchEvent(MotionEvent) line: 2403
PhoneWindow$DecorView(View).dispatchPointerEvent(MotionEvent) line: 9522 3)
ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl$QueuedInputEvent) line: 4247
ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl$QueuedInputEvent) line: 4097
ViewRootImpl$ViewPostImeInputStage(ViewRootImpl$InputStage).deliver(ViewRootImpl$QueuedInputEvent) line: 3643
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$InputStage).onDeliverToNext(ViewRootImpl$QueuedInputEvent) line: 3696
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$InputStage).forward(ViewRootImpl$QueuedInputEvent) line: 3662
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$AsyncInputStage).forward(ViewRootImpl$QueuedInputEvent) line: 3788
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$InputStage).apply(ViewRootImpl$QueuedInputEvent, int) line: 3670
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$AsyncInputStage).apply(ViewRootImpl$QueuedInputEvent, int) line: 3845
ViewRootImpl$NativePostImeInputStage(ViewRootImpl$InputStage).deliver(ViewRootImpl$QueuedInputEvent) line: 3643
ViewRootImpl$EarlyPostImeInputStage(ViewRootImpl$InputStage).onDeliverToNext(ViewRootImpl$QueuedInputEvent) line: 3696
ViewRootImpl$EarlyPostImeInputStage(ViewRootImpl$InputStage).forward(ViewRootImpl$QueuedInputEvent) line: 3662
ViewRootImpl$EarlyPostImeInputStage(ViewRootImpl$InputStage).apply(ViewRootImpl$QueuedInputEvent, int) line: 3670
ViewRootImpl$EarlyPostImeInputStage(ViewRootImpl$InputStage).deliver(ViewRootImpl$QueuedInputEvent) line: 3643
ViewRootImpl.deliverInputEvent(ViewRootImpl$QueuedInputEvent) line: 5939
ViewRootImpl.doProcessInputEvents() line: 5913 2)
ViewRootImpl.enqueueInputEvent(InputEvent, InputEventReceiver, int, boolean) line: 5874
ViewRootImpl$WindowInputEventReceiver.onInputEvent(InputEvent) line: 6042
ViewRootImpl$WindowInputEventReceiver(InputEventReceiver).dispatchInputEvent(int, InputEvent) line: 185
MessageQueue.nativePollOnce(long, int) line: not available [native method] 1)
MessageQueue.next() line: 323
Looper.loop() line: 135
ActivityThread.main(String[]) line: 5524
Method.invoke(Object, Object...) line: not available [native method]
ZygoteInit$MethodAndArgsCaller.run() line: 752
ZygoteInit.main(String[]) line: 642
关键点分析:
1)MessageQueue.nativePollOnce
消息循环,获取到jni层按键发给它的触屏事件,从jni转到java层来处理事件
2)ViewRootImpl.doProcessInputEvents
当前窗口的ViewRootImpl获取到事件,并开始处理
3)PhoneWindow$DecorView(View).dispatchPointerEvent
DecorView作为root的实例引用,开始接受事件进行处理。
4)Launcher(Activity).dispatchTouchEvent
通过cb,跳转到activity
5)--7)PhoneWindow.superDispatchTouchEvent
Activity又将事件传给PhoneWindow,逐步在各级child view里面传递,看谁会消耗事件。如果没有消耗,还会传给Activity进行onTouchEvent处理。Activity这里有两个作用,一是Activity实例可以提前捕获touch事件,做特殊处理,二是可以进行onTouchEvent处理。
8)--9)CellLayout.onInterceptTouchEvent
这里主要实现了应用层面view间的OnTouchListener。
5.2.3 OnTouchEvent栈分析
onTouchEvent被实现的地方很多,调用流程也各不相同,以下举例分析。
在launcher里的workspace里,onTouchEvent 和 OnTouchListener调用栈差异很小,也很微秒(底层是一样的,在栈顶附近略有区别):
Workspace(PagedView).onTouchEvent(MotionEvent) line: 2457
Workspace(View).dispatchTouchEvent(MotionEvent) line: 9302
Workspace(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2562
Workspace(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2245
Workspace.dispatchTouchEvent(MotionEvent) line: 8001
FrameLayout(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
Workspace.onTouch(View, MotionEvent) line: 1506
CellLayout.onInterceptTouchEvent(MotionEvent) line: 904
CellLayout(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2113
Workspace(ViewGroup).dispatchTransformedTouchEvent(MotionEvent, boolean, View, int) line: 2568
Workspace(ViewGroup).dispatchTouchEvent(MotionEvent) line: 2202
Workspace.dispatchTouchEvent(MotionEvent) line: 8001
Workspace和CellLayout都是ViewGroup的子类,却一个执行了View的dispatchTouchEvent ,一个执行了ViewGroup的dispatchTouchEvent,onTouchEvent只在View里被调用,所以能执行最终子类的onTouchEvent。
这种流程的区别在(ViewGroup).dispatchTransformedTouchEvent里,标黄的两个if语句决定了流程差异,
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {
// Calculate the number of pointers to deliver.
final int oldPointerIdBits = event.getPointerIdBits();
final int newPointerIdBits = oldPointerIdBits & desiredPointerIdBits;
// If the number of pointers is the same and we don't need to perform any fancy
// irreversible transformations, then we can reuse the motion event for this
// dispatch as long as we are careful to revert any changes we make.
// Otherwise we need to make a copy.
final MotionEvent transformedEvent;
if (newPointerIdBits == oldPointerIdBits) {
if (child == null || child.hasIdentityMatrix()) {
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
event.offsetLocation(offsetX, offsetY);
handled = child.dispatchTouchEvent(event);
event.offsetLocation(-offsetX, -offsetY);
}
return handled;
}
transformedEvent = MotionEvent.obtain(event);
} else {
transformedEvent = event.split(newPointerIdBits);
}
其中,desiredPointerIdBits又根据调用者的流程和参数而不同。在其上级调用中,mFirstTouchTarget是关键因素,标识当前根ViewGoup里,哪些view能接收和处理按键,mFirstTouchTarget链表的元素通过addTouchTarget添加进去。这个流程待后续详细分析。
另,上面讲的onTouchEvent都是view里面的处理,如果onTouchEvent在activity里面,它一般是用来处理触点在控件外的情形的。
- 按键分析--APP部分-- OnTouch事件处理流程
- 按键分析--APP部分-- OnClickListener事件处理流程
- 按键分析--APP部分-- OnLongClickListener事件处理流程
- 事件处理 onTouch onTouchEvent源码分析
- Android按键事件处理流程
- Android按键事件处理分析 .
- Android按键事件处理分析
- ontouch onclick事件处理
- Android按键事件处理流程 KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android按键事件处理流程 -- KeyEvent
- Android Activity的按键事件处理流程
- Android按键事件处理流程 -- KeyEvent
- ZStack协议按键处理流程分析
- qt按键事件处理机制分析
- onTouch和onClick事件处理
- android onTouch事件处理机制
- [UOJ#2] [NOI2014] 起床困难综合征
- Extention匿名类
- stringByAppendingPathComponent和stringByAppendingString的区别
- iOS开发之定位CLLocationManager
- [实践]使用JarJar优雅的发布依赖包
- 按键分析--APP部分-- OnTouch事件处理流程
- python2.7.11 win32位无法卸载
- java设计模式——单例模式
- [CodeVS2542]单词 做题笔记
- gitlab add ssh-key
- java 文件上传和下载处理
- tostring方法的陷进
- VIM使用教程
- 标准模板库(Standard Template Library,STL)学习