Flutter のイベント配布メカニズムの簡単な概要

Flutter のイベント配布の主なクラスである PointerEvent、HitTestResult、HitTestEntry、RenderObject、およびそれらの間の関係を理解する必要があります。

1. ポインタイベント

PointerEvent は、Flutter のすべてのイベントの基本クラスです。イベントの種類、場所、タイムスタンプ、デバイス情報などが含まれます。PointerEvent のサブクラスには、PointerDownEvent、PointerMoveEvent、PointerUpEvent などが含まれます。

2. ヒットテスト結果

HitTestResult はイベント配布の結果であり、イベント配布プロセス中にいくつかの情報が記録されます。HitTestResult には _hitTestEntries プライベート変数があり、これは List 型であり、イベント配信のプロセス (つまり HitTestEntry) を格納するために使用されます。

3. ヒットテストエントリー

HitTestEntry は、RenderObject と BoxHitTestResult を含むイベント配信のプロセスを記録します。RenderObjectはイベント配信処理における現在のノードに対応する描画オブジェクトを表し、BoxHitTestResultにはこのノードの位置情報が含まれる。

4.レンダーオブジェクト

RenderObject は、Flutter のレンダリング ツリー ノードの基本クラスであり、ノードの位置、サイズ、描画などの情報が含まれています。各ウィジェットは RenderObject に対応し、レンダリング時に対応する RenderObject に変換されます。

次に、Flutter でのイベント配信プロセスを詳しく分析してみましょう。

1. イベントの生成

イベントの生成は通常、画面のクリックやマウスのスライドなど、システムの最下位層によって行われます。システムがイベントを検出すると、そのイベントを PointerEvent オブジェクトにカプセル化し、Flutter エンジンに渡します。

2. イベントの配信

Flutter エンジンはイベントを受信すると、そのイベントをルート ノード、つまり PipelineOwner に対応する RenderObject に渡します。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