读Android源码之事件分发机制最全总结

一.概述

事件分发有多种类型, 本文主要介绍Touch相关的事件分发.

  • 整个事件分发流程中,会有大量MotionEvent对象,该对象用于记录所有与移动相关的事件,比如手指触摸屏幕事件。

  • 一次完整的MotionEvent事件,是从用户触摸屏幕到离开屏幕。整个过程的动作序列:ACTION_DOWN(1次) -> ACTION_MOVE(N次) -> ACTION_UP(1次),

  • 多点触摸,每一个触摸点Pointer会有一个id和index。对于多指操作,通过pointerindex来获取指定Pointer的触屏位置。比如,对于单点操作时获取x坐标通过getX(),而多点操作获取x坐标通过getX(pointerindex)

对于View,ViewGroup,Activity都能处理Touch事件, 它们之间处理的先后顺序和方法有所不同.

1.1 View

  • View是所有视图对象的父类,实现了动画相关的接口Drawable.Callback, 按键相关的接口KeyEvent.Callback, 交互相关的接口AccessibilityEventSource。比如Button继承自View。

  • TouchEvent事件处理相关的方法:

    • dispatchTouchEvent(MotionEvent event)

    • onTouchEvent(MotionEvent event)

1.2 ViewGroup

  • ViewGroup,是一个abstract类,一组View的集合,可以包含View和ViewGroup,是所有布局的父类或间接父类。继承了View,实现了ViewParent(用于与父视图交互的接口), ViewManager(用于添加、删除、更新子视图到Activity的接口)。比如常用的LinearLayout,RelativeLayout都是继承自ViewGroup。

  • TouchEvent事件处理相关的方法:

    • dispatchTouchEvent(MotionEvent event)

    • onInterceptTouchEvent(MotionEvent ev)

    • onTouchEvent(MotionEvent event)

1.3 Activity

  • Activity是Android四大基本组件之一,当手指触摸到屏幕时,屏幕硬件一行行不断地扫描每个像素点,获取到触摸事件后,从底层产生中断上报。再通过native层调用Java层InputEventReceiver中的dispatchInputEvent方法。经过层层调用,交由Activity的dispatchTouchEvent方法来处理。

  • TouchEvent事件处理相关的方法:

    • dispatchTouchEvent(MotionEvent event)

    • onTouchEvent(MotionEvent event)

二. 分发原理

Input系统—进程交互文章的小节[3.3]已介绍事件分发过程的前期工作. 当UI主线程收到底层上报的input事件,便会调用InputEventReceiver.dispachInputEvent方法.

2.1 DecorView.dispatchTouchEvent

[-> PhoneWindow.java ::DecorView]

此处cb是指Window的内部接口Callback. 对于Activity实现了Window.Callback接口. 故接下来调用Activity类.

2.2 Activity.dispatchTouchEvent

[-> Activity.java]

如果重写Activity的该方法,则会在分发事件之前拦截所有的触摸事件. 另外此处getWindow()返回的是Activity的mWindow成员变量, 该变量赋值过程是在Activity.attach()方法, 可知其类型为PhoneWindow.

2.2.1 Activity.onTouchEvent

[-> Activity.java]

2.3 superDispatchTouchEvent

[-> PhoneWindow.java]

PhoneWindow的最顶View是DecorView,再交由DecorView处理。而DecorView的父类的父类是ViewGroup,接着调用 ViewGroup.dispatchTouchEvent()方法。为了精简篇幅,有些中间函数调用不涉及关键逻辑,可能会直接跳过。

2.4 ViewGroup.dispatchTouchEvent

2.4.1 onFilterTouchEventForSecurity

根据隐私策略来过滤触摸事件。当返回true,表示继续分发事件;当返回flase,表示该事件应该被过滤掉,不再进行任何分发。

2.4.2 onInterceptTouchEvent

  • 当返回true,表示该事件被当前视图拦截;

  • 当返回false,继续执行事件分发。

2.4.3 buildOrderedChildList

获取一个视图组的先序列表,通过虚拟的Z轴来排序。

public float getZ() {    
    return getElevation() + getTranslationZ();
}

getZ()用于获取Z轴坐标。屏幕只有x,y坐标,而Z是虚拟的,可通过setElevation(),setTranslationZ()或者setZ()方法来修改Z轴的坐标值。

2.4.4 dispatchTransformedTouchEvent

该方法是ViewGroup真正处理事件的地方,分发子View来处理事件,过滤掉不相干的pointer ids。当子视图为null时,MotionEvent将会发送给该ViewGroup。最终调用View.dispatchTouchEvent方法来分发事件。

2.4.5 addTouchTarget
private TouchTarget addTouchTarget(View child, int pointerIdBits) {
    TouchTarget target = TouchTarget.obtain(child, pointerIdBits);
    target.next = mFirstTouchTarget;
    mFirstTouchTarget = target;    
    return target;
}

调用该方法,获取了TouchTarget,同时mFirstTouchTarget不再为null。

2.5 View.dispatchTouchEvent

[-> View.java]

  1. 先由OnTouchListener的OnTouch()来处理事件,当返回True,则消费该事件,否则进入2。

  2. onTouchEvent处理事件,的那个返回True时,消费该事件。否则不会处理

2.5.1 View.onTouchEvent

三. 总结

事件分发流程图:

  1. onInterceptTouchEvent返回值true表示事件拦截, onTouch/onTouchEvent 返回值true表示事件消费。

  2. 触摸事件先交由Activity.dispatchTouchEvent。再一层层往下分发,当中间的ViewGroup都不拦截时,进入最底层的View后,开始由最底层的OnTouchEvent来处理,如果一直不消费,则最后返回到Activity.OnTouchEvent

  3. ViewGroup才有onInterceptTouchEvent拦截方法。在分发过程中,中间任何一层ViewGroup都可以直接拦截,则不再往下分发,而是交由发生拦截操作的ViewGroup的OnTouchEvent来处理。

  4. 子View可调用requestDisallowInterceptTouchEvent方法,来设置disallowIntercept=true,从而阻止父ViewGroup的onInterceptTouchEvent拦截操作。

  5. OnTouchEvent由下往上冒泡时,当中间任何一层的OnTouchEvent消费该事件,则不再往上传递,表示事件已处理。

  6. 如果View没有消费ACTION_DOWN事件,则之后的ACTION_MOVE等事件都不会再接收。

  7. 只要View.onTouchEvent是可点击或可长按,则消费该事件.

  8. onTouch优先于onTouchEvent执行,上面流程图中省略,onTouch的位置在onTouchEvent前面。当onTouch返回true,则不执行onTouchEvent,否则会执行onTouchEvent。onTouch只有View设置了OnTouchListener,且是enable的才执行该方法。

MPU6050是一款广泛应用在惯性测量单元(IMU)中的微型传感器,由InvenSense公司生产。它集成了三轴加速度计和三轴陀螺仪,能够检测设备在三维空间中的线性加速度和角速度,进而计算出物体的姿态、运动和方向。在本项目中,MPU6050被用来获取设备的YAW、PITCH、ROLL这三个关键的姿态角,这些数据将通过OLED显示屏进行实时显示。 1. **MPU6050工作原理**: MPU6050内部包含两个主要传感器:加速度计用于测量重力加速度,提供X、Y、Z三个轴的线性加速度信息;陀螺仪则测量绕三个轴的旋转速率。通过融合这两个传感器的数据,可以计算出设备的动态运动状态。 2. **姿态角的定义**: - **YAW(偏航角)**:表示设备相对于一个参考方向的旋转角度,通常以水平面为基准。 - **PITCH(俯仰角)**:是设备沿垂直轴相对于水平面的倾斜角度,向上为正,向下为负。 - **ROLL(翻滚角)**:是设备围绕前向轴的旋转角度,向右为正,向左为负。 3. **数据处理与姿态解算**: 为了从原始的加速度和角速度数据中获取准确的姿态角,需要应用卡尔曼滤波、互补滤波或者Madgwick算法等高级数据融合方法。这些算法可以有效地消除噪声,提高姿态估计的稳定性和精度。 4. **OLED显示屏**: OLED(有机发光二极管)显示器是一种自发光技术,具有高对比度、快速响应时间以及广视角的优点。在该项目中,OLED用于实时显示YAW、PITCH、ROLL角,为用户提供了直观的视觉反馈。 5. **硬件连接与编程**: 实现这一功能需要将MPU6050通过I2C或SPI接口连接到微控制器(如Arduino、Raspberry Pi等)。编写相应的固件程序来取传感器数据,并将其转换为姿态角,然后将结果显示在OLED屏幕上。 6. **软件实现**: 在编程过程中,通常会用到相关的库文件,如Arduino IDE中的Wire库来处理I2C通信,Adafruit的MPU6050库来与传感器交互,以及Adafruit_GFX和Adafruit_SSD1306库来驱动OLED屏幕。 7. **调试与优化**: 项目实施过程中可能遇到的问题包括传感器漂移、数据不准确等,可以通过调整滤波器参数、校准传感器以及优化算法来改善。 综上,"MPU6050(OLED显示姿态角)"项目涉及了传感器技术、微控制器编程、数据融合算法、嵌入式显示等多个领域的知识,对于学习和实践物联网、机器人、无人机等领域的开发者来说,是一个很好的动手实践项目。
基于C#开发的一个稳定可靠的上位机系统,旨在满足工业控制的需求。该系统集成了多个功能界面,如操作界面、监控界面、工艺流显示界面、工艺表界面、工艺编辑界面、曲线界面和异常报警界面。每个界面都经过精心设计,以提高用户体验和工作效率。例如,操作界面和监控界面对触摸屏友好,支持常规点击和数字输入框;工艺流显示界面能够实时展示工艺步骤并变换颜色;工艺表界面支持Excel和加密文件的导入导出;工艺编辑界面采用树形编辑方式;曲线界面可展示八组曲线并自定义纵坐标数值;异常报警界面能够在工艺流程出现问题时及时报警。此外,该系统还支持与倍福TC2、TC3和西门子PLC1200/300等下位机设备的通信,确保生产线的顺畅运行。系统参考欧洲工艺软件开发,已稳定运行多年,证明了其可靠性和稳定性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对C#编程有一定基础的人群。 使用场景及目标:适用于需要构建高效、稳定的工业控制系统的企业和个人开发者。主要目标是提升生产效率、确保生产安全、优化工艺流程管理和实现数据的有效管理与传输。 其他说明:文中提供了部分示例代码片段,帮助者更好地理解具体实现方法。系统的复杂度较高,但凭借C#的强大功能和开发团队的经验,确保了系统的稳定性和可靠性。
内容概要:本文详细介绍了OpenMV在机器视觉领域的高级应用,涵盖基础回顾、高级功能详解、高级编程技巧、进阶应用场景及实战项目。OpenMV作为基于机器视觉的开源嵌入式系统,广泛应用于工业检测、智能安防、机器人等领域。文中深入探讨了图像处理技术(如滤波、边缘检测、特征检测与匹配、图像分割)、对象检测与跟踪(如Haar级联分类器、深度学习目标检测、卡尔曼滤波)等高级功能。此外,文章还讲解了多线程编程、算法优化、内存管理和并行计算等编程技巧,并展示了OpenMV在工业检测、智能交通和医疗领域的具体应用案例。最后,通过构建智能安防系统的实战项目,演示了OpenMV在入侵检测和人脸识别方面的应用。 适合人群:具备一定编程基础和技术背景的工程师或研究人员,尤其是对机器视觉、嵌入式系统感兴趣的从业者。 使用场景及目标:①掌握OpenMV的基础和高级功能,应用于工业检测、智能安防、机器人等领域的项目开发;②通过多线程编程和性能优化技术,提升程序的运行效率和响应速度;③学习如何利用OpenMV实现图像处理、对象检测与跟踪等复杂任务,满足实际应用场景的需求。 阅建议:本文内容丰富,涵盖了从理论到实战的各个方面,建议者结合实际项目需求,逐步学习和实践文中提到的技术和方法。特别是对于高级功能和编程技巧部分,可以通过动手实验加深理解。同时,关注最新的技术和算法进展,以适应不断发展的机器视觉领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值