当一个人点击网页上的后退按钮时,Riverpod 给出了一个错误的状态异常
Riverpod giving a bad state exception when one hits back button on webpage
当我点击他们网页上的后退按钮时,我在我的 StateNotifiers 中收到这个错误。我已将其隔离到 longRunningAPI
请求下方的位置。
Exception has occurred.
"Error: Bad state: Tried to use RunListNotifier after `dispose` was called.
我有这样的代码。
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);
}
}
}
在捕获中简单地做这样的事情安全吗?
} catch (e) {
if (e.runtimeType.toString() == 'StateError') {
// ignore the error
} else {
state = AsyncError(e);
}
}
我相信您可以通过在 API 调用之后设置状态之前检查 mounted
来解决这个问题,如下所示:
List<Run> stuff = await read(apiProvider).longRunningAPI(param: param);
if (!mounted) return;
state = AsyncData(stuff);
这只是检查是否调用了 dispose,如果调用了,请不要尝试修改状态。
另一个可能有用的资源是在您的 API 调用中添加 cancelToken
并在提供商被处置时取消。
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;
});
然后您必须将 cancelToken 添加到您的实际请求中。 marvel example project by the author of Riverpod can be found here.
中的一个很好的例子
当我点击他们网页上的后退按钮时,我在我的 StateNotifiers 中收到这个错误。我已将其隔离到 longRunningAPI
请求下方的位置。
Exception has occurred.
"Error: Bad state: Tried to use RunListNotifier after `dispose` was called.
我有这样的代码。
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);
}
}
}
在捕获中简单地做这样的事情安全吗?
} catch (e) {
if (e.runtimeType.toString() == 'StateError') {
// ignore the error
} else {
state = AsyncError(e);
}
}
我相信您可以通过在 API 调用之后设置状态之前检查 mounted
来解决这个问题,如下所示:
List<Run> stuff = await read(apiProvider).longRunningAPI(param: param);
if (!mounted) return;
state = AsyncData(stuff);
这只是检查是否调用了 dispose,如果调用了,请不要尝试修改状态。
另一个可能有用的资源是在您的 API 调用中添加 cancelToken
并在提供商被处置时取消。
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;
});
然后您必须将 cancelToken 添加到您的实际请求中。 marvel example project by the author of Riverpod can be found here.
中的一个很好的例子