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

相关推荐
Flutter OH4 小时前
Flutter OH 卡死冻屏问题定位指南
flutter·命令模式
2501_916007475 小时前
Flutter与游戏App加固避坑指南:如何为混合开发与高交互应用选对安全方案?
安全·flutter·游戏·ios·小程序·uni-app·iphone
恋猫de小郭6 小时前
Flutter A2UI 深度解析,它是怎么提供动态生产力的,然后为什么 A2UI 不只是 Flutter
android·前端·flutter
恋猫de小郭1 天前
Android 17 + OkHttp 5.5.0 ,全新 ECH 下你的 HTTPS 域名可以请求时被安全隐藏
android·前端·flutter
「、皓子~2 天前
海狸IM 2.1 正式发布
flutter·微服务·golang·electron·开源软件·im·海狸im
里欧跑得慢2 天前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
恋猫de小郭2 天前
AI 时代,一个优化 Flutter 的重复代码工具 Deslop
android·前端·flutter
ljt27249606613 天前
Flutter笔记--envied
前端·笔记·flutter