flutter的事件分发机制简单总结

news/2024/7/20 21:35:08 标签: flutter, android, ios

我们需要了解Flutter中事件分发的主要类:PointerEvent、HitTestResult、HitTestEntry、RenderObject,以及它们之间的关系。

1. PointerEvent

PointerEvent是Flutter中所有事件的基类。它包含了事件的类型、位置、时间戳、设备信息等。PointerEvent的子类包括PointerDownEvent、PointerMoveEvent、PointerUpEvent等。

2. HitTestResult

HitTestResult是事件分发的结果,它记录了事件分发过程中的一些信息。HitTestResult中有一个_hitTestEntries私有变量,它是一个List类型,用来存储事件分发的过程(即HitTestEntry)。

3. HitTestEntry

HitTestEntry记录了事件分发的过程,它包含了一个RenderObject和一个BoxHitTestResult。RenderObject表示事件分发过程中当前节点对应的渲染对象,而BoxHitTestResult则包含了这个节点的位置信息。

4. RenderObject

RenderObject是Flutter中渲染树节点的基类,它包含了节点的位置、大小、绘制等信息。每个widget都对应一个RenderObject,在渲染时会被转换为对应的RenderObject。

下面,我们来详细分析一下Flutter中事件分发的流程。

1. 事件的生成

事件的生成通常由系统底层完成,例如点击屏幕或者滑动鼠标等。当系统检测到事件时,会将事件封装成PointerEvent对象,并传递给Flutter引擎。

2. 事件的传递

Flutter引擎收到事件后,会将事件传递给根节点对应的RenderObject,即PipelineOwner。PipelineOwner会创建一个HitTestResult对象,用来记录事件分发的结果。

3. 事件的分发

在PipelineOwner中,会调用_renderView.hitTest方法,将事件分发给渲染树中的节点。hitTest方法的实现如下:

void hitTest(HitTestResult result, Offset position) {
  assert(attached);
  final HitTestEntry entry = HitTestEntry(this);
  result.add(entry);
  if (hitTestChildren(result, position)) {
    handleEvent(entry);
  }
}

在这个方法中,首先创建了一个HitTestEntry对象,将其添加到HitTestResult中记录分发结果。然后调用hitTestChildren方法,将事件继续向下传递。如果事件被处理了,则调用handleEvent方法处理事件。

hitTestChildren方法的实现如下:

bool hitTestChildren(HitTestResult result, Offset position) {
  RenderObject child = lastChild;
  while (child != null) {
    final bool hit = child.hitTest(result, position: position);
    if (hit)
      return true;
    child = childBefore(child);
  }
  return false;
}

在这个方法中,先遍历当前节点的所有子节点,调用它们的hitTest方法,将事件向下传递。如果子节点中有处理事件的节点,则返回true,否则返回false。

4. 事件的处理

当事件到达目标节点时,会调用该节点的handleEvent方法来处理事件。handleEvent方法的实现因节点类型而异,例如GestureDetector会调用onTap、onDoubleTap等回调函数来处理事件,而RenderBox则会调用handleEventForBox方法来处理事件。

handleEventForBox方法的实现如下:

void handleEventForBox(HitTestEntry entry, PointerEvent event) {
  bool absorbed = hitTestSelf();
  if (!absorbed && size.contains(event.localPosition)) {
    handleEvent(entry, event);
    absorbed = true;
  }
  if (!absorbed)
    absorbPointer(event);
}

在这个方法中,首先调用hitTestSelf方法来判断节点是否可以处理事件。如果节点不能处理事件,则调用absorbPointer方法将事件标记为已处理。如果节点可以处理事件,则调用handleEvent方法来处理事件,并将事件标记为已处理。

5. 事件的冒泡

当事件处理完成后,会将事件向上传递,直到到达根节点。这个过程与事件的分发类似,只不过是从当前节点的父节点开始向上传递。

在整个事件分发的过程中,每个RenderObject都会创建一个HitTestEntry对象,将其添加到HitTestResult中记录分发结果。在最终处理事件时,Flutter会遍历HitTestResult中的HitTestEntry对象,依次调用每个RenderObject的事件处理回调函数。

Flutter中事件分发的详细流程和实现。需要注意的是,事件分发的过程是非常复杂的,它涉及到许多细节和优化,例如事件缓存、事件模拟、事件合并等,这些细节和优化对于提高应用的性能和响应速度非常重要。


http://www.niftyadmin.cn/n/261224.html

相关文章

每日一个小技巧:1分钟告诉你截图翻译软件哪个好用

随着互联网的发展,我们对各种语言文字的翻译需求越来越高。在翻译时,大家经常会遇到一些生词或专业术语,这时候我们就需要使用翻译软件来帮助理解。但是,有些时候大家需要翻译的内容并不是一段文本,而是一张图片或截图…

Java 新的生态型应用开发框架,Solon v2.2.13 发布

Java 新的生态型应用开发框架,Solon :更快、更小、更简单。从零开始构建,有自己的标准规范与开放生态: 150多个生态插件,可以满足各种场景开发大量的国产框架适配,可以为应用软件国产化提供更好支持&#…

Keepass 使用

Keepass 使用 参考:(16 封私信 / 81 条消息) keepass - 搜索结果 - 知乎 (zhihu.com) 下载和安装 🇨🇳 中文语言包安装 ​ 1️⃣ 安装并运行 KeePass(安装时默认英文,无中文可选); ​ 2️⃣…

np.diff()函数

np.diff函数 调用方法示例1示例2 这里记录一下 np.diff() 算法的用法。 调用方法 import numpy as npnp.diff(a, n1, axis-1, prepend<no value>, append<no value>)[source]各个参数意义&#xff1a; a&#xff1a;输入数组。 n&#xff1a;可选参数&#xff0c…

【MySQL入门指南】MySQL中的数据类型总结

文章目录 MySQL数据类型一、数值类型1.类型总览2.BIT类型3.INT系列类型4.浮点数类型1)float与double2.float与decimal 二、字符串类型1.类型总览2.CHAR类型3.VARCHAR类型 三、日期与时间类型四、枚举类型1.enum类型2.set类型3.在set中的查找 MySQL数据类型 ​ MySQL中支持的数…

【电科复试第一名】23上交819考研经验分享

笔者来自通信考研小马哥23上交819全程班学员 819&#xff0c;上岸经验贴&#xff0c;知无不言 初试第十一&#xff0c;复试第一&#xff0c;总分第七(与第六同分) 考研经历:本科就读与湖南某末985&#xff0c;大学时间没好好学习&#xff0c;天天打王者&#xff0c;玩steam上…

UML--类图--软件工程系统学习-- idea查看类图-类关系图

文章目录 什么是类图类图的用途类图的组成 类什么是类类符号类关系依赖&#xff08;Dependence&#xff09;idea查看依赖 关联关系&#xff08;association&#xff09;继承/泛化idea查看继承 实现&#xff08;realization&#xff09;聚合组成组合和聚合之间的差异 类图详解id…

java异常处理 throws、throw、try...catch..finally

Java 中的异常有很多&#xff0c;这种异常机制&#xff0c;可以帮助处理程序中未知的错误。关于异常的处理有try catch 程序块、throw 、throws 1.throws throws方式处理异常又被称之为声明异常&#xff0c;将问题标识出来&#xff0c;报告给调用者。如果方法内通过throw抛出了…