【flutter源码】手势处理过程

源码执行顺序看不懂的可以先看看这个 -> 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重写,里面只处理了一些结束手势的事件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值