一.前言

刚学习Android的朋友们可能以会使用控件为主要任务,但是我们随着学习Android的深入,会不断接触到Android的事件流,也就是Android的事件分布机制.可能有些人觉得这和你有什么关系,你可能觉得不了解我照样做app,但是博主建议你还是熟悉它比较好,因为博客学习Android的时候,需要熟悉它的时候有以下几种:

1.自定义控件的时候

2.在某些情况下的bug,比如ListView的OnItemClickListener的onItemClick方法失效

3.某些情况下要获取用户的按键情况,比如你想屏蔽后退键

还有其他的一些情况,博客暂时想到的就这些了,不过肯定还有其他你需要熟悉它的时候


今天博客就重点基于Android 6.0的源码,解析一下事件的分发机制

首先先引用别人的一张我们看到的视图层次机构图,因为博主自己画就太丑了,哈哈


从这里我们可以看出,ViewGroup是一个容器,它可以承载View或者其他的ViewGroup容器,而ViewGroup本身又继承了View,所以ViewGroup是View的一个扩展.这是对上图的一个简单的介绍,好了,下面是正文

二.解析View的事件分发

首先贴出View的事件分发的主要源代码

    public boolean dispatchTouchEvent(MotionEvent event) {                boolean result = false;        final int actionMasked = event.getActionMasked();        //安全性的拦截方法,检查view是不是被覆盖了        if (onFilterTouchEventForSecurity(event)) {            //noinspection SimplifiableIfStatement            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;            }        }        return result;    }
       //在事件分发的时候做一个安全性的检测,检测View是不是被遮盖,如果被遮盖返回false,否则返回true,true表示应该分发事件
    public boolean onFilterTouchEventForSecurity(MotionEvent event) {        //noinspection RedundantIfStatement        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {            // Window is obscured, drop this touch.            return false;        }        return true;    }


部分无关紧要的代码已经剔除,不然代码不仅长,而且牵扯太多其他的东西

从上面的代码我们看到了View的事件分发,在分发的时候,我们可以清楚的看到调用了一

个检测安全性的方法,如果通过了才可以分发事件.检测啥,上面我已经清除的注释了,这里

不再陈述.

紧接着程序拿到一个ListenerInfo对象,这个对象是什么呢?从字面上理解,应该是一个有关监听的信息的类,那我们就去查看一下

static class ListenerInfo {protected OnFocusChangeListener mOnFocusChangeListener;private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;protected OnScrollChangeListener mOnScrollChangeListener;private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;public OnClickListener mOnClickListener;protected OnLongClickListener mOnLongClickListener;/protected OnContextClickListener mOnContextClickListener;protected OnCreateContextMenuListener mOnCreateContextMenuListener;private OnKeyListener mOnKeyListener;private OnTouchListener mOnTouchListener;private OnHoverListener mOnHoverListener;private OnGenericMotionListener mOnGenericMotionListener;private OnDragListener mOnDragListener;private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;}

一看,原来是一个接口保存的'仓库'啊,我们可以看到View有关的监听是不是都在里头了呢,点击事件,长按事件。。。。,很多很多,应该是为了避免在View中写太多的成员变量,所以才分离出来的

那我们上面的代码就可以看懂啦!过了安全的检测之后就是四个判断


1.判断保存接口信息的li是不是为空

2.li里面的mOnTouchListener接口是不是为空,说白了也就是你有没有设置这个View的触摸事件

3.View是不是不能用的状态,默认是可用的,通过xx.setEnabled(false)就可以设置成无用的状态啦

4.触摸接口mOnTouchListener的方法onTouch返回的是不是true


这里也就很清楚的看到了,View通过设置监听回调的mOnTouchListener的触摸事件onTouch是比View的其他事件都要早的,如果你监听了该事件,那么你就有绝对的权利控制事件是否能流到其他的地方


如果在设置的触摸接口的回调方法onTouch方法中返回了一个true,那么变量result就会被置为true,所以下面的View自身的onTouch事件将不会再被调用,反之View自身的onTouchEvent事件被调用,而View的点击事件就是在onTouchEvent方法中调用的,所以View的点击事件如果失效了,就针对View本身来说有如下可能:

1.事件被mOnTouchListener的方法onTouch消费了,也就是这里返回的是true

2.你重写View的onTouchEvent方法的时候没有调用super.onTouchEvent(e)方法


下一篇介绍ViewGroup的事件分发

阅读完如果觉得哪里有问题或者需要纠正的地方请留言,不甚感激~~~

更多相关文章

  1. 如何在eclipse的android工程里引用android sdk之外的类和方法
  2. 深入探讨 Android(安卓)传感器
  3. Android(安卓)坐标系及动画移动坐标相关集合
  4. Android中丰富多彩的onTouch事件
  5. Android获取本机电话号码的简单方法
  6. 一张图带你掌握Android(安卓)Q上InputDispatcher事件分发流程(系
  7. Android(安卓)结束进程的方法
  8. android studio在模拟器上的中文乱码问题解决方法
  9. Android5.x+ 格式化外部存储(u盘, sdcard)的方法

随机推荐

  1. 关于android textview 中英文混合分行错
  2. Android开发点滴 - 实现层级式导航(API 1
  3. Android(安卓)贪吃贪游戏(源码详解和改进)
  4. Android(安卓)ORM数据库框架之-greenDao(
  5. Android数据库升级、降级、创建(onCreate
  6. android 手机存储文件夹学习
  7. Android复习笔记(13)-Fragment的使用(1)
  8. Android中的getDimension,getDimensionPi
  9. Mac系统下,配置Android(安卓)gradle环境
  10. WebView的基本使用