Flutter在启动时(runApp
)会进行一些洒水类的”粘合”,WidgetsFlutterBinding作为主类,需求粘合一系列的Binding,其中GestureBinding
便是事情处理类;
GestureBinding是Flutter中办理手势事情的Binding,是Flutter Framework层处理事情的最起点;
GestureBinding实现了HitTestable, HitTestDispatcher, HitTestTarget,别离具有以下功用
-
hitTest
射中测验 -
dispatchEvent
事情分发 -
handleEvent
处理事情()
成员变量:
//触点路由,由手势辨认器注册,会把手势辨认器的pointer和handleEvent存入
//以便在GestureBinding.handleEvent调用
final PointerRouter pointerRouter = PointerRouter();
//手势竞技场办理者,办理竞技场们的相关操作
final GestureArenaManager gestureArena = GestureArenaManager();
//hitTest列表,里边存储了被射中测验成员
final Map<int, HitTestResult> _hitTests = <int, HitTestResult>{};
GestureBinding在_handlePointerDataPacket
办法接收有Engine层传递过来的触点数据,经过数据包装转换为Framework层可处理的数据:PointerAddedEvent、PointerCancelEvent、PointerDownEvent、PointerMoveEvent、PointerUpEvent
等等,随后在_handlePointerEventImmediately
办法中进行射中测验和事情分发;
手指按下
当手指按下时,接收到的事情类型是PointerDownEvent
首先是射中测验
当事情类型是event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent
会进行新的射中测验,射中测验相关请看这,得到射中测验列表后,开始调用dispatchEvent
进行事情分发。
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);
}
}
事情分发
事情分发的目的是调用射中对象的handleEvent
办法以处理相关逻辑,比如咱们熟知的Listener组件,它做的事便是回调相关办法,比如按下时Listener会回调onPointerDown
## 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);
}
咱们知道射中测验最终会把GestrueBinding本身加入到列表中,所以最终也会履行GestrueBinding的handleEvent办法
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