写点什么

Android View 的事件分流源码,安卓内存优化管理器

用户头像
Android架构
关注
发布于: 42 分钟前

|---View


| |---boolean dispatchTouchEvent(MotionEvent event)


| |--- boolean onTouchEvent(MotionEvent event)


[](


)1.1 dispatchTouchEvent: 如果事件由视图处理,则为 true,否则为 false。


===========================================================================================================


public boolean dispatchTouchEvent(MotionEvent event) {


// If the event should be handled by accessibility focus first.


if (event.isTargetAccessibilityFocus()) {


// We don't have focus or no virtual descendant has it, do not handle the event.


if (!isAccessibilityFocusedViewOrHost()) {


return false;


}


// We have focus and got the event, then use normal event dispatch.


event.setTargetAccessibilityFocus(false);


}


boolean result = false;


if (mInputEventConsistencyVerifier != null) {


mInputEventConsistencyVerifier.onTouchEvent(event, 0);


}


final int actionMasked = event.getActionMasked();


if (actionMasked == MotionEvent.ACTION_DOWN) {


// Defensive cleanup for new gesture


stopNestedScroll();


}


if (onFilterTouchEventForSecurity(event)) {


if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {


result = true;


}


// 重点 判断 listenerInfo 中是否有事件 listenter 并且 mOnTouchListener.onTouc 返回 true


ListenerInfo li = mListenerInfo;


if (li != null && li.mOnTouchListener != null


&& (mViewFlags & ENABLED_MASK) == ENABLED


&& li.mOnTouchListener.onTouch(this, event)) {


result = true;


}


// 第二个重点,如果上述判断为 false,并且 onTouchEventr 返回为 true,消耗事件


if (!result && onTouchEvent(event)) {


result = true;


}


}


if (!result && mInputEventConsistencyVerifier != null) {


mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);


}


// Clean up after nested scrolls if this is the end of a gesture;


// also cancel it if we tried an ACTION_DOWN but we didn't want the rest


// of the gesture.


if (actionMasked == MotionEvent.ACTION_UP ||


actionMasked == MotionEvent.ACTION_CANCEL ||


(actionMasked == MotionEvent.ACTION_DOWN && !result)) {


stopNestedScroll();


}


return result;


}


  1. dispatchTouchEvent 中 final int actionMasked = event.getActionMasked();

  2. ListenerInfo :将 view 所有的 listener 信息封装到一个对象中。

  3. 在该方法中有两个判断:


ListenerInfo li = mListenerInfo;


if (li != null && li.mOnTouchListener != null


&& (mViewFlags & ENABLED_MASK) == ENABLED


&& li.mOnTouchListener.onTouch(this, event)) {


result = true;


}


if (!result && onTouchEvent(event)) {


result = true;


}


复制代码


如果 onTouchEvent 或者是 onTouchListenner 是 true 的话,会消费此事件,同时,在这里也走了 onTouchEvent


  • boolean onTouchEvent

  • MotionEvent.ACTION_UP:调用了 PerformClick()


[](


)三个问题:


==============================================================


[](


)1. 在 activity 中调用了


==========================================================================


mTouchView.setOnTouchListener(new View.OnTouchListener() {


@Override


public boolean onTouch(View v, MotionEvent event) {


Log.e("TAG", "onTouch: " + event.getAction());


return false;


}


});


mTouchView.setOnClickListener(new View.OnClickListener() {


@Override


public void onClick(View v) {


Log.e("TAG", "onClick: " );


}


});


/TabLayout*/


@Override


public boolean onTouchEvent(MotionEvent event) {


Log.e("TAG", "onTouchEvent: "+event.getAction());


return super.onTouchEvent(event);


}


复制代码


执行顺序:


[](


)2. 如果是 Tablyout 中直接 return ture 呢?


========================================================================================


不执行 onClick,因为 onClick 在 View.OntouchEvent 中的 ACTION_UP 中,若直接 return true 就不会走 super 中的方法。


[](


)3. 如果是 dispatchEvent return true 呢?


===========================================================================================


什么都不执行


[](


)分发流程


=============================================================


super.dispatchEvent->ListenerInfo->super.onTouchEvent(event)->ACTION_UP->performListener().


复制代码


[](


)2. ViewGroup 的事件分发:


============================================================================


首先是 actionDown:


if (actionMasked == MotionEvent.ACTION_DOWN


|| mFirstTouchTarget != null) { //


final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;


if (!disallowIntercept) {


intercepted = onInterceptTouchEvent(ev);


ev.setAction(action); // restore action in case it was changed


} else {


intercepted = false;


}


}


复制代码


  • mFirstTouchTarget: 这个很重要,只有在第一次按下的时候才会调用 disallowIntercept,如果之后想要改变效果的时候,这是一个坑。


|---ViewGroup


| |---dispatchTouchEvent


| | |---onInterceptTouchEvent(ev


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


)




有 View 会消耗时间的情况(比如点击,onTouchListener)


  • 第一次按下进来(down)—>ViewGroup.dispatchTouchEvent—>ViewGroup.onInterceptTouchEvent(ev)–>view.dispatchEvent—(view 的那一套)

  • 第二次进来(move)ViewGroup.dispatchTouchEvent—>ViewGroup.onInterceptTouchEvent(ev)–>view.dispatchEvent—(view 的那一套)

  • 第三次(up)ViewGroup.dispatchTouchEvent—>ViewGroup.onInterceptTouchEvent(ev)–>view.dispatchEvent—(view 的那一套)–>view.onClick




子****View 中没有消费事件的情况。只走一遍


  • 第一次进来(down)ViewGroup.dispatchTouchEvent—>ViewGroup.onInterceptTouchEvent(ev)–>view.dispatchEvent—view.onTouch–>onTouch Event


[](


)viewGroup 的源码分析


=======================================================================


actionDown

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android View的事件分流源码,安卓内存优化管理器