Android开发

Android 事件分发之追本溯源

本文主要是介绍Android 事件分发之追本溯源,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

  • Android设备的界面交互带来了非常好的体验,在我们日常使用中,无时无刻不在触发着事件的分发;比如点击了淘宝某个图片,比如点击了掘金APP的某个按钮,都会触发系统的事件分发;
  • Android 事件分发也是自定义View很重要的一个知识点,搞懂事件分发,当自定义View或者解决滑动冲突的问题,都会显得胸有成竹了;
  • 和以往结合源码的方式讲解相比,更想通过另一种有趣的角度来分析,接下来让我们正式开始吧;

1. 为什么要有事件分发机制?

1.1,Android手机

Android手机作为手持设备,界面显示区域并不是很大,为了有便携的效果,只能牺牲手机的显示区域;这就会带来一个问题,可视内容少;为了不影响用户体验,我们必须要在有限的区域做更多的展示,这就对界面的设计有很高的要求了;假如我们是Google的工程师,我们要怎么来设计界面,以此带来好的体验效果呢?

1.2,脑洞一

第一种设计:将界面显示区域切割,根据所需要显示的视图,切割为无数块,每一块对应着一部分视图;如下:

这种界面设计简单粗暴,需要多少个视图,就将界面切割成多少个视图模块,以此来放下所有的视图内容;当然,这样设计显而易见会有问题,当视图越来越多的时候,每一个视图的模块所能展示的区域就会越来越小,这样体验效果是肯定不行的;

1.3,脑洞二

第二种设计:既然通过切割显示区域以此来展示视图的方案有问题,那么我们就来试试重叠的效果吧;如下:

这种设计很好的解决了视图模块过多时,显示区域不够展示的问题;但是也会存在问题,每一个显示区域和用户的交互顺序混乱了,比如我要和模块为4的视图做交互,结果触发了视图5的交互效果,而脑洞一方案则没有该问题;既然如此,那么我们能不能针对脑洞二的方案来进行优化呢?
答案是:有的!

1.3,设计交互机制

当多个模块视图重叠时,要协调好与用户的交互就极其重要了,毕竟涉及到用户体验;

当用户的触碰屏幕的显示区域,我们并不知道哪个模块需要和用户进行交互,而我们又不能让用户和其中一个模块的交互失效,那么我们只能去遍历重叠的模块,由内部的视图来决定是否需要相应用户的操作;

这样就可以解决多个模块视图重叠时,哪个模块需要相应用户交互的问题了;

而这正是Android的事件分发机制;

当然上面只是我的脑洞,用于方便理解,如果你有更好的想法,可以和我交流;

那么这种机制是怎么来实现这种效果的呢?请继续往下看;

在深入分析事件分发之前,先来了解一下事件的来源;

2. 事件是什么,是怎么产生的?

2.1,事件的来源

当屏幕被触摸,Linux内核会将硬件产生的触摸事件包装为Event存到/dev/input/event[x]目录下。

接着,系统创建的一个InputReaderThread线程loop起来让EventHub调用getEvent()不断的从/dev/input/文件夹下读取输入事件。

然后InputReader则从EventHub中获得事件交给InputDispatcher。

而InputDispatcher又会把事件分发到需要的地方,比如ViewRootImpl的WindowInputEventReceiver中。

这里只是简单了解一下大概的流程,源码过于复杂,这里不做具体的分析;

概括之:当触摸屏幕的时候,硬件会捕捉到用户的触摸动作,告诉系统内核,系统内核将该事件保存下来,然后有一个线程会将这个事件读取出来,交由专门分发的类进行分发;

2.2,事件

当屏幕被触摸时,系统底层会将触摸事件(坐标和时间等)封装成MotionEvent事件返回给上层 View;从用户首次触摸屏幕开始,经历手指在屏幕表面的任何移动,直到手指离开屏幕时结束都会产生一系列事件;

MotionEvent的类型:

  • MotionEvent.ACTION_DOWN:当屏幕检测到第一个触点按下之后就会触发到这个事件
  • MotionEvent.ACTION_MOVE:当触点在屏幕上移动时触发;
  • MotionEvent.ACTION_UP:当触点松开时被触发;
  • MotionEvent.ACTION_CANCEL:由系统在需要的时候触发,不由用户直接触发;

3. 事件分发机制是怎么实现的?

3.1,设计模式

在分析事件分发机制之前,我们先来看一下事件分发涉及的设计模式;

这个设计模式是事件分发机制的核心,Google工程师是通过这个设计模式来设计事件分发机制的;理解了这个设计模式有助于我们理解事件分发机制;

而这个设计模式就是责任链模式;

3.2,责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

下面我们通过一段伪代码来解读这个模式:

    // 请求
        switch (request) {
            case 0:
                // 对象一接收请求并处理
                break;
            case 1:
                // 对象二接收请求并处理
                break;
            case 2:
                // 对象三接收请求并处理
                break;
            case 3:
                // 对象四接收请求并处理
                break;
            case 4:
                // 对象五接收请求并处理
                break;
                    
这篇关于Android 事件分发之追本溯源的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!