Flutter Hooks 与 flutter_map_animations 冲突:第二次地图动画报错的解决方案

Flutter Hooks 与 flutter_map_animations 冲突:第二次地图动画报错的解决方案

HookWidget 中使用 flutter_map_animations 时,如果把 useSingleTickerProvider() 传给 AnimatedMapController

dart 复制代码
final tickerProvider = useSingleTickerProvider();

final animatedMapController = useMemoized(
  () => AnimatedMapController(
    vsync: tickerProvider,
  ),
);

第一次地图动画可以正常执行。

第二次执行动画时,会抛出:

css 复制代码
A SingleTickerProviderStateMixin can only be used as a TickerProvider once.

If a State is used for multiple AnimationController objects, or if it is
passed to other objects and those objects might use it more than one time
in total, then instead of mixing in a SingleTickerProviderStateMixin,
use a regular TickerProviderStateMixin.

原因是 useSingleTickerProvider() 只能创建一个 Ticker,而 AnimatedMapController 在多次地图动画中可能创建多个 AnimationController

flutter_hooks 已经有一个增加 useMultiTickerProvider() 的 PR:

github.com/rrousselGit...

但该功能还没有进入正式版本,因此可以先在项目中加入一个自定义实现:

dart 复制代码
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

TickerProvider useMultiTickerProvider({List<Object?>? keys}) {
  return use(
    keys != null
        ? _MultiTickerProviderHook(keys)
        : const _MultiTickerProviderHook(),
  );
}

class _MultiTickerProviderHook extends Hook<TickerProvider> {
  const _MultiTickerProviderHook([List<Object?>? keys])
      : super(keys: keys);

  @override
  _MultiTickerProviderHookState createState() =>
      _MultiTickerProviderHookState();
}

class _MultiTickerProviderHookState
    extends HookState<TickerProvider, _MultiTickerProviderHook>
    implements TickerProvider {
  final Set<Ticker> _tickers = <Ticker>{};

  ValueListenable<bool>? _tickerModeNotifier;

  @override
  Ticker createTicker(TickerCallback onTick) {
    final ticker = Ticker(
      onTick,
      debugLabel: 'created by $context (multi)',
    );

    _updateTickerModeNotifier();

    _tickers.add(ticker);

    _updateTickers();

    return ticker;
  }

  @override
  void dispose() {
    assert(() {
      for (final ticker in _tickers) {
        if (ticker.isActive) {
          throw FlutterError(
            'useMultiTickerProvider created Ticker(s), but at the time '
            'dispose() was called on the Hook, at least one of those Tickers '
            'was still active.',
          );
        }
      }

      return true;
    }(), '');

    _tickerModeNotifier?.removeListener(_updateTickers);
    _tickerModeNotifier = null;

    _tickers.clear();

    super.dispose();
  }

  @override
  TickerProvider build(BuildContext context) {
    _updateTickerModeNotifier();
    _updateTickers();

    return this;
  }

  void _updateTickers() {
    if (_tickers.isEmpty) {
      return;
    }

    final muted =
        !(_tickerModeNotifier?.value ?? TickerMode.of(context));

    for (final ticker in _tickers) {
      ticker.muted = muted;
    }
  }

  void _updateTickerModeNotifier() {
    final newNotifier = TickerMode.getNotifier(context);

    if (newNotifier == _tickerModeNotifier) {
      return;
    }

    _tickerModeNotifier?.removeListener(_updateTickers);

    newNotifier.addListener(_updateTickers);

    _tickerModeNotifier = newNotifier;
  }

  @override
  String get debugLabel => 'useMultiTickerProvider';

  @override
  bool get debugSkipValue => true;
}

然后把:

dart 复制代码
final tickerProvider = useSingleTickerProvider();

改成:

dart 复制代码
final tickerProvider = useMultiTickerProvider();

final animatedMapController = useMemoized(
  () => AnimatedMapController(
    vsync: tickerProvider,
  ),
);

useSingleTickerProvider() 替换为 useMultiTickerProvider(),避免 AnimatedMapController 第二次创建动画时触发单 Ticker 限制。

相关推荐
君赏10 小时前
棉宇宙 Flutter 热更新是如何落地的
flutter
恋猫de小郭12 小时前
AndroidX 新增 Security State ,支持可编程的系统安全状态查询
android·前端·flutter
zihan51812 小时前
自己做软件日记9/21 得到了一个良好的文件结构框架
后端·flutter·前端框架·android studio
ZFJ_张福杰1 天前
【Flutter】Flutter 中有哪些耗时操作?从 UI 卡顿到 Isolate 性能优化
flutter·性能优化·卡顿·isolate
sakiko_1 天前
Flutter:Dart学习笔记1:基础UI组件等
flutter
9765033352 天前
iOS 上架 4.3a 被拒【uniapp专讲】
flutter·ios·objective-c·uniapp·swift
传奇开心果编程2 天前
【Flutter入门练中学】第2课:布局系统
学习·flutter·ui
君赏2 天前
FlutterPatch:把 Shorebird 热更新的控制面搬回自己服务器
flutter
用户2181697049302 天前
Flutter tootip 轻量级提示
flutter
用户2181697049302 天前
Flutter 拖拽 Draggable DragTarget
flutter