flutter 事件分发源码解析2 dispatchEvent

还是以下面代码为入口去分析
runApp(
  MaterialApp(
    home: Scaffold(
      appBar: AppBar(),
      body: GestureDetector(
        child: GestureDetector(
          child: const Text("点击事件"),
          onTap: () {
            log.log("GestureDetector ---2");
          },
        ),
        onTap: () {
          log.log("GestureDetector ---1");
        },
      ),
    ),
  ),
);
 

分析前先说明dispatchEvent大概流程。 flutter把所有命中测试放到了集合里面, 在分发的时候循环集合调用目标的目标的 handleEvent 这时候判断目标有没有手势识别器(注意入口代码是以带入手势识别器去分析,如果没有手势识别器又是另外一种分发逻辑)有手势识别器把当前识别器添加到路由。完成整个循环后调用路由管理去调用识别器接口(识别器有很多,但是触发的只能一个,所以多个识别器会竞争。路由管理只有两种策略,一种第一个就满足, 一种是只剩最后一个就满足)

GestureBindin
void _handlePointerEventImmediately(PointerEvent event) {
...省略
  if (hitTestResult != null ||
      event is PointerAddedEvent ||
      event is PointerRemovedEvent) {
    assert(event.position != null);
    dispatchEvent(event, hitTestResult);
  }
}

void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
  ...省略
  for (final HitTestEntry entry in hitTestResult.path) {
    try {
//注意这里实际是调用的render 的handleEvent. 后面会调用识别器的handleEvent
      entry.target.handleEvent(event.transformed(entry.transform), entry);
    } catch (exception, stack) {
      ...省略
      ));
    }
  }
}

以上一篇最后一张图开始进入分析text我们没有添加手势识别器 所以往父类在找

GestureDetector 

我们监听了点击事件,在build里面发现了, 它自动添加了点击的手势识别器

@override
Widget build(BuildContext context) {
  final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
//我们实现了点击事件
  if (onTapDown != null ||
      onTapUp != null ||
      onTap != null ||
     ,,,省略
  ) {
//添加手势点击识别器
    gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
      () => TapGestureRecognizer(debugOwner: this),
      (TapGestureRecognizer instance) {
        instance
          ..onTapDown = onTapDown
          ..onTapUp = onTapUp
//把我们实现的点击事件赋值给创建的识别器
          ..onTap = onTap
       ...省略
      },
    );
  }

...省略  如果我们实现了其他事件也会添加对应识别器(这里可以看出GestureDetector组件都是在组合各种识别器)
  return RawGestureDetector(
//把识别器集合传入进去
    gestures: gestures,
    behavior: behavior,
    excludeFromSemantics: excludeFromSemantics,
    child: child,
  );
}

RawGestureDetectorState

上一步返回的RawGestureDetector ,看其实现的state build 

@override
Widget build(BuildContext context) {
//又在外面包裹了一层Listener 并且实现了onPointerDown 
  Widget result = Listener(
    onPointerDown: _handlePointerDown,
    behavior: widget.behavior ?? _defaultBehavior,
    child: widget.child,
  );
  if (!widget.excludeFromSemantics) {
    result = _GestureSemantics(
      behavior: widget.behavior ?? _defaultBehavior,
      assignSemantics: _updateSemanticsForRenderObject,
      child: result,
    );
  }
  return result;
}

这里可以看到  Listener的。触摸事件是调用了识别器。(这里就是开头说明  有识别器和没有识别器的分发会逻辑会不一致。如果不用识别器后面一系列带识别器的分发都不会走了)  这个路由后面在分析现在继续往下走

void _handlePointerDown(PointerDownEvent event) {
  assert(_recognizers != null);
  for (final GestureRecognizer recognizer in _recognizers!.values)
    recognizer.addPointer(event);
}
RenderPointerListener
RawGestureDetectorState 里面又包裹了  Listener  _GestureSemantics  主要分析Listener 。 Listener里面最终创建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 PointerSignalEvent)
    return onPointerSignal?.call(event);
}
最后回调的是RawGestureDetectorState._handlePointerDown

void _handlePointerDown(PointerDownEvent event) {
  assert(_recognizers != null);
//中间会有一个数据的转换方法_syncAll,这个可以自己看就不再放出来
  for (final GestureRecognizer recognizer in _recognizers!.values)
//识别器添加当前事件
    recognizer.addPointer(event);
}
GestureRecognizer
void addPointer(PointerDownEvent event) {
//保存此事件
  _pointerToKind[event.pointer] = event.kind;
//是否允许跟踪指针默认true(与GestureArenaManager有关)
  if (isPointerAllowed(event)) {
    //添加跟踪
    addAllowedPointer(event);
  } else {
    handleNonAllowedPointer(event);
  }
}
BaseTapGestureRecognizer

我们实现的 TapGestureRecognizer 调用父类的方法

@override
void addAllowedPointer(PointerDownEvent event) {
  assert(event != null);

//默认ture
  if (state == GestureRecognizerState.ready) {
         ...省略
    _down = event;
  }
  if (_down != null) {
    super.addAllowedPointer(event);
  }
}
PrimaryPointerGestureRecognizer
@override
void addAllowedPointer(PointerDownEvent event) {
//这一步就是添加识别器到路由
  super.addAllowedPointer(event);
  if (state == GestureRecognizerState.ready) {
//添加成功后改变状态 
    _state = GestureRecognizerState.possible;
    _primaryPointer = event.pointer;
    _initialPosition = OffsetPair(local: event.localPosition, global: event.position);
       //默认true。deadline默认100
    if (deadline != null)
      _timer = Timer(deadline!, () => didExceedDeadlineWithEvent(event));
  }
}
OneSequenceGestureRecognizer

根据上一步调用super.addAllowedPointer(event) 最终到达startTrackingPointer

@protected
void startTrackingPointer(int pointer, [Matrix4? transform]) {
//添加当前识别器到全局路由, 
//pointer 就是事件id
//handleEvent 就是回调方法
//transform 简单说就是坐标转换
  GestureBinding.instance!.pointerRouter.addRoute(pointer, handleEvent, transform);
//保存当前事件id
  _trackedPointers.add(pointer);
  assert(!_entries.containsValue(pointer));
 //保存手势竞争
  _entries[pointer] = _addPointerToArena(pointer);
}

把当前识别器放入到GestureArenaManager 添加竞争

GestureArenaEntry _addPointerToArena(int pointer) {
  if (_team != null)
    return _team!.add(pointer, this);
  return GestureBinding.instance!.gestureArena.add(pointer, this);
}
BaseTapGestureRecognizer

//上一步完成后。继续往下执行 调用didExceedDeadlineWithEvent。 最终调用TapGestureRecognizer.didExceedDeadline.  后者又调用_checkDown

void _checkDown() {
//默认flase
  if (_sentTapDown) {
    return;
  }
//这个方法进入后会不满足条件而不执行, 所以就不往里走
  handleTapDown(down: _down!);
//所以第二次 GestureDetector 就不会玩下走
  _sentTapDown = true;
}

这时候每个都会这样调用 handleEvent 直到调用 hitTestResult 最后一个 才会有变化

GestureBinding

//hitTestResult 循环到最后一个就会调用 GestureBinding .handleEvent

@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) {
     //再次接受到up指令直接让第一个识别器胜利 回调   
    gestureArena.sweep(event.pointer);
  } else if (event is PointerSignalEvent) {
    pointerSignalResolver.resolve(event);
  }
}
PointerRouter

路由开始处理已有的识别器

void route(PointerEvent event) {
..省略
调用
  _dispatchEventToRoutes(event, _globalRoutes, copiedGlobalRoutes);
}
void _dispatchEventToRoutes(
  PointerEvent event,
  Map<PointerRoute, Matrix4?> referenceRoutes,
  Map<PointerRoute, Matrix4?> copiedRoutes,
) {
  copiedRoutes.forEach((PointerRoute route, Matrix4? transform) {
//判断之前的路由是否还存在(可能会在循环中删掉路由,有些元素 竞技成功 其他的同类路由监听的就会删掉)
    if (referenceRoutes.containsKey(route)) {
//循环调用
      _dispatch(event, route, transform);
    }
  });
}
void _dispatch(PointerEvent event, PointerRoute route, Matrix4? transform) {
  try {
    event = event.transformed(transform);
//回调每个handleEvent
    route(event);
  } catch (exception, stack) {
....省略
  }
}
PrimaryPointerGestureRecognizer

其他省略。直接跳转到   TapGestureRecognizer.handleEvent   自己没有复写 最后调用

PrimaryPointerGestureRecognizer.handleEvent
@override
void handleEvent(PointerEvent event) {
  assert(state != GestureRecognizerState.ready);
//这时候满足条件状态变了
  if (state == GestureRecognizerState.possible && event.pointer == primaryPointer) {
    ...省略

    if (event is PointerMoveEvent && (isPreAcceptSlopPastTolerance || isPostAcceptSlopPastTolerance)) {
      resolve(GestureDisposition.rejected);
      stopTrackingPointer(primaryPointer!);
    } else {
                //调用
      handlePrimaryPointer(event);
    }
  }
  stopTrackingIfPointerNoLongerDown(event);
}

@override
void handlePrimaryPointer(PointerEvent event) {
//因为传过来的是触摸事件所以不满足。循环到结束
  if (event is PointerUpEvent) {
//直到传过来up
    _up = event;
    _checkUp();
  } ...省略
}

入口代码有两个GestureDetector 所以会触发两次
//两次都会不满足条件而不执行
void _checkUp() {
//直到执行gestureArena.sweep(event.pointer) 调用第一个组件的acceptGesture 其他的调用rejectGesture
  if (!_wonArenaForPrimaryPointer || _up == null) {
    return;
  }
  assert(_up!.pointer == _down!.pointer);

//触发GestureDetector 的回调 (完结。这是带有识别器的分发逻辑)
  handleTapUp(down: _down!, up: _up!);
  _reset();
}
@override
void acceptGesture(int pointer) {
  super.acceptGesture(pointer);
  if (pointer == primaryPointer) {
    _checkDown();
//这时候只置为ture
    _wonArenaForPrimaryPointer = true;
//再次调用 看上一段
    _checkUp();
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值