当点击网页上的后退按钮时,Riverpod 会给出错误状态异常

foo*_*675 7 flutter riverpod

当有人点击网页上的后退按钮时,我在 StateNotifiers 中收到此错误。我已将其隔离到下面请求的地方longRunningAPI

Exception has occurred.
"Error: Bad state: Tried to use RunListNotifier after `dispose` was called.
Run Code Online (Sandbox Code Playgroud)

我有这样的代码。

final runListController = StateNotifierProvider.autoDispose
    .family<RunListNotifier, AsyncValue<List<Run>>, RunListParameter>(
        (ref, param) {
  return RunListNotifier(read: ref.read, param: param);
});

class RunListNotifier extends StateNotifier<AsyncValue<List<Run>>> {
  RunListNotifier({required this.read, required this.param})
      : super(AsyncLoading()) {
    fetchViaAPI(param);
  }

  final Reader read;
  final RunListParameter param;
  void fetchViaAPI(RunListParameter param) async {
    state = AsyncLoading();
    try {
      List<Run> stuff = await read(apiProvider).longRunningAPI(param: param);
      state = AsyncData(stuff);
    } catch (e) {
      state = AsyncError(e);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在 catch 中简单地做这样的事情是否安全?

    } catch (e) {
      if (e.runtimeType.toString() == 'StateError') {
         // ignore the error
      } else {
         state = AsyncError(e);
      }
    }

Run Code Online (Sandbox Code Playgroud)

Ale*_*ord 7

mounted我相信您可以通过在 API 调用后设置状态之前进行检查来解决此问题,如下所示:

List<Run> stuff = await read(apiProvider).longRunningAPI(param: param);
if (!mounted) return;
state = AsyncData(stuff);
Run Code Online (Sandbox Code Playgroud)

这只是检查是否调用了 dispose,如果是,则不要尝试修改状态。

另一个可能有用的资源是将 a 添加cancelToken到您的 API 调用中,并在提供程序被处置时取消。

final longRunningApi = FutureProvider.autoDispose.family<List<Run>, RunListParameter>((ref, param) async {
  final cancelToken = CancelToken();
  ref.onDispose(cancelToken.cancel);

  final api = await ref.watch(apiProvider);
  final res = await api.longRunningApi(param, cancelToken);
  
  ref.maintainState = true;
  return res;
});
Run Code Online (Sandbox Code Playgroud)

然后您必须将 cancelToken 添加到您的实际请求中。可以在此处找到 Riverpod 作者的Marvel 示例项目中的一个很好的示例。