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

Flutter中如何将Stream转为Listenable供go_router的refreshListenable使用

实现方案

1. 编写 Stream 转 Listenable 的适配类

因为 GoRouter 的 refreshListenable 参数要求传入 Listenable 类型,我们可以基于 ChangeNotifier 做一层适配,监听鉴权流的变化时自动发送通知:

import 'package:flutter/foundation.dart';

class AuthStateListenable extends ChangeNotifier {
  late final StreamSubscription _authSubscription;

  AuthStateListenable(Stream<bool> authStateStream) {
    // 每次鉴权状态变化时触发通知,让GoRouter执行重定向逻辑
    _authSubscription = authStateStream.listen((_) => notifyListeners());
  }

  @override
  void dispose() {
    _authSubscription.cancel();
    super.dispose();
  }
}

2. 新增对应Provider

我们新增两个Provider,分别暴露可监听的鉴权状态对象,以及直接可读的登录状态值:

// 提供给GoRouter的refreshListenable
final authStateListenableProvider = Provider.autoDispose<AuthStateListenable>((ref) {
  final authService = ref.watch(authServiceProvider);
  final listenable = AuthStateListenable(authService.isLoggedIn);
  // 自动销毁资源
  ref.onDispose(() => listenable.dispose());
  return listenable;
});

// 直接提供登录状态,方便在重定向逻辑中读取
final isLoggedInProvider = StreamProvider.autoDispose<bool>((ref) {
  final authService = ref.watch(authServiceProvider);
  return authService.isLoggedIn;
});

3. 配置GoRouter

推荐在main函数中初始化Provider容器,再完成路由的配置,避免跨上下文读取Provider的问题:

void main() {
  // 初始化Riverpod容器
  final providerContainer = ProviderContainer();
  // 读取鉴权监听对象
  final authListenable = providerContainer.read(authStateListenableProvider);

  final router = GoRouter(
    refreshListenable: authListenable,
    redirect: (context, state) {
      // 读取当前登录状态
      final isLoggedIn = providerContainer.read(isLoggedInProvider).valueOrNull ?? false;
      final isOnAuthRoute = state.matchedLocation == '/signin';

      // 未登录且不在登录页则跳转到登录页
      if (!isLoggedIn && !isOnAuthRoute) return '/signin';
      // 已登录且在登录页则跳转到首页
      if (isLoggedIn && isOnAuthRoute) return '/';
      return null;
    },
    // 其余路由配置省略
  );

  runApp(
    ProviderScope(
      parent: providerContainer,
      child: MyApp(router: router),
    ),
  );
}

内容的提问来源于stack exchange,提问作者Florian Leeser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:36:03