You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter AutoRoute reevaluateListenable仅单次生效问题求助

问题描述

使用Flutter的AutoRoute包时,通过reevaluateListenable监听Settings Cubit的流,但该监听仅生效一次,必须重启应用才能再次触发导航守卫的重新评估。相关代码如下:

app.dart 代码

class MizanitiApp extends StatelessWidget {
  MizanitiApp({super.key});

  final AppRouter router = AppRouter();

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
            lazy: false,
            create: (context) => locator<SettingsCubit>()..initiated()),
        BlocProvider(
            create: (context) => locator<WalletsWatcherCubit>()..initiated()),
      ],
      child: BlocConsumer<SettingsCubit, SettingsState>(
        listenWhen: (previous, current) =>
            previous.failureOrSuccessOption != current.failureOrSuccessOption,
        listener: (context, state) {
          state.failureOrSuccessOption.fold(
            () => null,
            (either) => either.fold(
              // failure
              (Failure failure) =>
                  _onSettingsFailure(context: context, failure: failure),
              // success
              (_) => _onSettingsSuccess(context: context),
            ),
          );
        },
        buildWhen: (previous, current) =>
            previous.domain.theme != current.domain.theme,
        builder: (context, state) {
          return MaterialApp.router(
            title: 'Mizaniti App',
            themeMode: state.domain.theme.getOrNull(),
            darkTheme:
                ThemeData(useMaterial3: true, brightness: Brightness.dark),
            theme: ThemeData(
              colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
              useMaterial3: true,
            ),
            routerConfig: router.config(
                reevaluateListenable: ReevaluateListenable.stream(
                    context.read<WalletsWatcherCubit>().stream)),
          );
        },
      ),
    );
  }
}

Guard 代码

class BiometricGuard extends AutoRouteGuard {
  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) async {
    final BuildContext? context = router.navigatorKey.currentContext;

    optionOf(context).fold(
      () => resolver.next(),
      (context) {
        print('fingerprint');
        final bool isAppGuarded =
            context.read<SettingsCubit>().state.isAppGuarded;

        if (isAppGuarded) {
          router.replaceAll([const BiometricGuardRoute()]);
          return;
        }

        resolver.next();
      },
    );
  }
}
解决方案

1. 修正监听的流对象

当前reevaluateListenable绑定的是WalletsWatcherCubit的流,而非目标的SettingsCubit,导致Settings状态变化无法触发路由守卫重评估。修改router.config部分:

routerConfig: router.config(
  reevaluateListenable: ReevaluateListenable.stream(
    context.read<SettingsCubit>().stream
  )
),

2. 让守卫响应状态更新

原守卫仅在导航触发时读取一次isAppGuarded值,需添加状态监听,确保状态变化时能重新处理导航逻辑:

class BiometricGuard extends AutoRouteGuard {
  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) async {
    final BuildContext? context = router.navigatorKey.currentContext;

    optionOf(context).fold(
      () => resolver.next(),
      (context) {
        final settingsCubit = context.read<SettingsCubit>();
        final isAppGuarded = settingsCubit.state.isAppGuarded;

        if (isAppGuarded) {
          router.replaceAll([const BiometricGuardRoute()]);
          // 监听后续状态变化,当守卫关闭时继续导航
          final subscription = settingsCubit.stream.listen((state) {
            if (!state.isAppGuarded) {
              resolver.next();
              subscription.cancel(); // 状态变化后取消订阅,避免内存泄漏
            }
          });
          return;
        }

        resolver.next();
      },
    );
  }
}

3. 确保SettingsCubit正确发射状态

检查SettingsCubit中更新isAppGuarded的逻辑,确保每次状态变化都调用emit发射新状态:

class SettingsCubit extends Cubit<SettingsState> {
  // ... 其他初始化逻辑
  void updateAppGuardStatus(bool isGuarded) {
    final updatedDomain = state.domain.copyWith(isAppGuarded: isGuarded);
    emit(state.copyWith(domain: updatedDomain));
  }
}

4. 调整BlocConsumer的build条件(可选)

如果需要在Settings其他状态变化时重建路由配置,可以放宽buildWhen的条件,但核心问题已通过前几步解决。

内容的提问来源于stack exchange,提问作者hesham shawky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:54:50