源码执行顺序看不懂的可以先看看这个 -> WidgetsFlutterBinding是怎样使用mixin的
Android端:
MainActivity
-> FlutterActivity //
-> createFlutterView()
-> FlutterView //重写onTouchEvent,获取手势事件
-> this.androidTouchProcessor.onTouchEvent(event) //将手势透传给AndroidTouchProcessor
-> addPointerForIndex() //组装数据
-> this.renderer.dispatchPointerDataPacket(packet, packet.position()) //FlutterRenderer 调用JNI方法将数据传递给Flutter层
-> this.flutterJNI.dispatchPointerDataPacket(buffer, position);
Flutter层:
-> hooks.dart: @pragma('vm:entry-point')_dispatchPointerDataPacket //被Native层调用
-> PlatformDispatcher.instance._dispatchPointerDataPacket(packet) //透传到PlatformDispatcher中_dispatchPointerDataPacket方法
-> onPointerDataPacket //回调函数
-> GestureBinding: platformDispatcher.onPointerDataPacket = _handlePointerDataPacket; //回调函数在GestureBinding中赋值
-> _handlePointerDataPacket()
->_pendingPointerEvents.addAll() //将组装的手势数据添加到进_pendingPointerEvents队列
-> _flushPointerEventQueue() //循环队列调用handlePointerEvent
-> handlePointerEvent()
->_handlePointerEventImmediately() //根据事件类型处理, 一般情况下: Down 事件用来记录,Up 事件用来结束,其他的事件做分发
->
记录事件
-> hitTestResult = HitTestResult(); //存放事件命中集合
-> hitTest(hitTestResult, event.position); //命中测试
-> RendererBinding.hitTest() //先执行RendererBinding的hitTest()方法 (为什么这么执行可以看开头的另一篇文章)
-> renderView.hitTest(result, position: position); //递归调用child!.hitTest(), 子级优先添加进hitTestResult
-> super.hitTest(result, position); //递归完成执行父类语句,添加GestureBinding本身
->_hitTests[event.pointer] = hitTestResult; //以手势id为key保存手势数据
分发处理事件:
->dispatchEvent(event, hitTestResult);
-> for( entry.target.handleEvent(); ) //遍历hitTestResult,给GestureBinding和所有命中的child分发事件
-> handleEvent() //事件处理,命中的renderView调用自己的handleEvent(),最后GestureBinding也调用handleEvent()
先看renderView调用自己的handleEvent():
-> renderView.handleEvent() //我们可以看到RenderView没有实现handleEvent()方法,RenderView继承自RenderObject,而RenderObject中的handleEvent()方法是一个空实现可以被重写,因此此处调用最终走到了重写了该方法的子类中,例如RenderPointerListener.handleEvent(); RenderPointerListener是Listener的最终实现,后面会写到。
再看GestureBinding的handleEvent()
-> pointerRouter.route(event); //事件路由处理(route 是一个回调函数,简单理解为哪里注册了route,事件就会回调到哪里)
-> _dispatchEventToRoutes() //遍历_routeMap
->_dispatch()
-> 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);
}
如果是 PointerDownEvent 事件,那么 gestureArena 就关闭掉,关闭的意思是:
如果竞技场中只有一个元素,那么该元素就获胜,获得获得手势处理权,就开始处理手势。
如果竞技场中没有元素,那么没有元素获胜。
如果竞技场中有特别渴望胜利的,那么特别渴望胜利的就获得手势处理权,
比如 EagerGestureRecognizer,这个机会很少,因为会打破默认的处理。
如果是 PointerUpEvent 事件,那么就需要竞争了 sweep 。竞争的结果就是第一个获得手势处理权,其他的手势拒绝手势。
以上代码就是flutter从android原生拿到手势事件的分发过程,我们以Listener和GestureDetector为例,看看它们是怎样获取手势事件的
Listener
->Listener extends SingleChildRenderObjectWidget //Listener没有build方法,所以我们先看父类
//注:为什么会执行createElement()和mount()方法,可以去看开头的widgetsBiding文章
->createElement() => SingleChildRenderObjectElement(this) //SingleChildRenderObjectWidget中实现了createElement()方法,创建了SingleChildRenderObjectElement(this)
->element.mount() //创建Element后会调用Element的mount()方法
->super.mount(parent, newSlot); //先执行父类的mount方法
->createRenderObject() //父类中调用了createRenderObject()方法
->Listener.createRenderObject()//执行子类重写的createRenderObject()方法
->RenderPointerListener() //最终创建了RenderPointerListener()类
->RenderPointerListener extends RenderProxyBoxWithHitTestBehavior extends RenderProxyBox extends RenderBox extends RenderObject implements HitTestTarget //RenderPointerListener的继承关系
->handleEvent() //RenderPointerListener实现了handleEvent()方法
->RenderPointerListener.handleEvent() //命中测试时,此处会存储在HitTestResult中,通过entry.target.handleEvent()回调数据
//RenderPointerListener.handleEvent()代码如下:
@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 PointerPanZoomStartEvent) {
return onPointerPanZoomStart?.call(event);
}
if (event is PointerPanZoomUpdateEvent) {
return onPointerPanZoomUpdate?.call(event);
}
if (event is PointerPanZoomEndEvent) {
return onPointerPanZoomEnd?.call(event);
}
if (event is PointerSignalEvent) {
return onPointerSignal?.call(event);
}
}
///我们可以看到Listener拿到手势事件后没有做任何处理,只是根据事件类型做了分发
GestureDetector以点击事件为例
TapGestureRecognizer的继承关系,下方会用到:
TapGestureRecognizer extends BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer
extends OneSequenceGestureRecognizer extends GestureRecognizer extends GestureArenaMember
//事件注册
GestureDetector
->RawGestureDetector //GestureDetector中创建了一个事件集合gestures(GestureRecognizerFactoryWithHandlers工厂创建GestureRecognizer的子类, 点击事件创建的是TapGestureRecognizer),最终return的是一个RawGestureDetector
->Listener(onPointerDown: _handlePointerDown...) //RawGestureDetector创建的是一个Listener,那么问题来了,GestureDetector和Listener有什么区别呢?
->_handlePointerDown() //当Listener获取到onPointerDown事件时,会透传给_handlePointerDown函数
->recognizer.addPointer(event); //遍历之前创建的gestures集合,调用addPointer()方法
->addAllowedPointer(event); //调用addAllowedPointer(event); 而recognizer.addPointer是一个空方法,往下看子类的实现
->BaseTapGestureRecognizer.addAllowedPointer(event); //TapGestureRecognizer的继承关系TapGestureRecognizer extends BaseTapGestureRecognizer extends PrimaryPointerGestureRecognizer extends OneSequenceGestureRecognizer extends GestureRecognizer extends GestureArenaMember,最终执行了BaseTapGestureRecognizer的addAllowedPointer(event);方法
->PrimaryPointerGestureRecognizer.addAllowedPointer(event); //被super调用
->OneSequenceGestureRecognizer.addAllowedPointer(event); //被super调用
->startTrackingPointer() //OneSequenceGestureRecognizer.addAllowedPointer(event)中调用
->_entries[pointer] = _addPointerToArena(pointer); //startTrackingPointer()中调用
->GestureBinding.instance.gestureArena.add(pointer, this); //将pointer添加至GestureArenaManager中的_arenas,加入手势竞技!
->state.members.first.acceptGesture(pointer); //当手势竞技成功,就会走该回调
->BaseTapGestureRecognizer.acceptGesture() //根据继承关系,实现该方法的最后一个子类是BaseTapGestureRecognizer
->_checkDown()
->handleTapDown() //子类实现
->TapGestureRecognizer.handleTapDown() //竞争成功后,最终在此处响应手势事件
//我们回到OneSequenceGestureRecognizer.startTrackingPointer()方法
->GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform); //注册了一个回调到GestureBinding中的pointerRouter中,而通过上文
手势事件分发我们知道,命中测试的最后会添加GestureBinding本身,也就是说GestureBinding也能获取到手势事件,并通过pointerRouter路由分发
->OneSequenceGestureRecognizer.handleEvent() //handleEvent获取到来自GestureBinding的手势事件
->PrimaryPointerGestureRecognizer.handleEvent() //被PrimaryPointerGestureRecognizer重写
->handlePrimaryPointer(event); //该方法被BaseTapGestureRecognizer重写,里面只处理了一些结束手势的事件