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 限制。

相关推荐
好的佩奇1 天前
Dart 之增强枚举
android·flutter·dart
好的佩奇1 天前
蓝牙之无线电与通信距离
android·flutter·蓝牙
程序员老刘·3 天前
从短剧App的bug看响应式编程在AI时代的优势
flutter·ai编程·跨平台开发
传奇开心果编程3 天前
【Flutter踩坑排雷】第7课:巨型 build 函数坑|全部 UI 写在同一个 build,维护难、隐性异常
android·flutter·ios·移动开发·跨平台·dart·声明式ui
程序员老刘3 天前
从短剧App的bug看响应式编程在AI时代的优势
flutter·ai编程·客户端
恋猫de小郭4 天前
最近 Android 有什么更新:Android Dev Summit 2026 技术解读
android·前端·flutter
好的佩奇4 天前
Dart 之类修饰符
android·flutter·dart
好的佩奇015 天前
Dart 之类修饰符
android·flutter·dart
Jewel1055 天前
文字为什么总是不居中!记录一个bug
android·flutter·ios
2601_949847755 天前
Form-data 跨端三方库仓颉适配全流程
前端·javascript·flutter