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

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

猜你喜欢

转载自blog.csdn.net/qq_28563283/article/details/130349463