GestureBinding of Flutter events

When Flutter starts ( runApp), it will perform some "bonding" of watering classes. WidgetsFlutterBinding is the main class and needs to glue a series of Bindings, among which GestureBindingis the event processing class;

GestureBinding is the Binding that manages gesture events in Flutter, and is the starting point for the Flutter Framework layer to process events;

GestureBinding implements HitTestable, HitTestDispatcher, HitTestTarget, and has the following functions respectively

  • hitTesthit test
  • dispatchEventevent distribution
  • handleEventhandle event()

Member variables:

//触点路由,由手势识别器注册,会把手势识别器的pointer和handleEvent存入
//以便在GestureBinding.handleEvent调用
final PointerRouter pointerRouter = PointerRouter();

//手势竞技场管理者,管理竞技场们的相关操作
final GestureArenaManager gestureArena = GestureArenaManager();

//hitTest列表,里面存储了被命中测试成员
final Map<int, HitTestResult> _hitTests = <int, HitTestResult>{};
复制代码

GestureBinding _handlePointerDataPacketreceives the contact data passed by the Engine layer in the method, and converts it into data that can be processed by the Framework layer after data packaging: PointerAddedEvent、PointerCancelEvent、PointerDownEvent、PointerMoveEvent、PointerUpEventetc., and then _handlePointerEventImmediatelyperforms hit testing and event distribution in the method;

finger press

When the finger is pressed, the received event type is PointerDownEvent

first hit test

When the event type is event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEventa new hit test, see here for hit test related. After getting the hit test list, start calling dispatchEventfor event distribution.

void _handlePointerEventImmediately(PointerEvent event) {
  HitTestResult? hitTestResult;
  if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent) {
    assert(!_hitTests.containsKey(event.pointer));
    hitTestResult = HitTestResult();
    hitTest(hitTestResult, event.position);
    if (event is PointerDownEvent) {
      _hitTests[event.pointer] = hitTestResult;
    }
    assert(() {
      if (debugPrintHitTestResults)
        debugPrint('$event: $hitTestResult');
      return true;
    }());
  } else if (event is PointerUpEvent || event is PointerCancelEvent) {
    hitTestResult = _hitTests.remove(event.pointer);
  } else if (event.down) {
    //当前事件是按下状态,重用hitTest结果
    hitTestResult = _hitTests[event.pointer];
  }
  if (hitTestResult != null ||
      event is PointerAddedEvent ||
      event is PointerRemovedEvent) {
    assert(event.position != null);
    dispatchEvent(event, hitTestResult);
  }
}
复制代码

event distribution

The purpose of event distribution is to call the method of the hit object handleEventto process related logic, such as the well-known Listener component, what it does is to call back related methods, such as Listener will call back when pressedonPointerDown

## GestureBinding ##
@override // from HitTestDispatcher
void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
  assert(!locked);
  if (hitTestResult == null) {
    assert(event is PointerAddedEvent || event is PointerRemovedEvent);
    try {
      pointerRouter.route(event);
    } catch (exception, stack) {
      ...
    }
    return;
  }
  for (final HitTestEntry entry in hitTestResult.path) {
    try {
      entry.target.handleEvent(event.transformed(entry.transform), entry);
    } catch (exception, stack) {
      ...
    }
  }
}
复制代码
## Listener ##
@override
void handleEvent(PointerEvent event, HitTestEntry entry) {
  assert(debugHandleEvent(event, entry));
  if (event is PointerDownEvent)
    return onPointerDown?.call(event);
  if (event is PointerMoveEvent)
    return onPointerMove?.call(event);
  if (event is PointerUpEvent)
    return onPointerUp?.call(event);
  if (event is PointerHoverEvent)
    return onPointerHover?.call(event);
  if (event is PointerCancelEvent)
    return onPointerCancel?.call(event);
  if (event is PointerSignalEvent)
    return onPointerSignal?.call(event);
}
复制代码

We know that the hit test will add GestrueBinding itself to the list at the end, so the handleEvent method of GestrueBinding will also be executed at the end

handleEvent

GestrueBinding.handleEvent是处理手势识别器相关的逻辑,pointerRouter.route(event)调用了识别器的handleEvent方法(需要提前进行触点注册),随后的是竞技场的相关处理;可以看这里了解手势识别器;

## GestrueBinding ##
@override // from HitTestTarget
void handleEvent(PointerEvent event, HitTestEntry entry) {
  pointerRouter.route(event);

  if (event is PointerDownEvent) {
    gestureArena.close(event.pointer);
  } else if (event is PointerUpEvent) {
    gestureArena.sweep(event.pointer);
  } else if (event is PointerSignalEvent) {
    pointerSignalResolver.resolve(event);
  }
}
复制代码

手指抬起,

手指抬起会重用之前hitTest结果,并不会重新hitTest,如果是Listener组件,则会回调PointerUpEvent

Guess you like

Origin juejin.im/post/7087873740658180133