[英]Unhandled Exception: Bad state: Tried to use StateNotifier after `dispose` was called
I'm using riverpod to manage my app states and struggling with the last provider.我正在使用riverpod 来管理我的应用程序状态并与最后一个提供者苦苦挣扎。 Basically, I'm using Firebase auth provider and have a Firestore document (FirestoreUser) for each user that matches on auth uid.
基本上,我使用的是 Firebase 身份验证提供程序,并且每个用户都有一个与身份验证 uid 匹配的 Firestore 文档(FirestoreUser) 。
For the app to function properly I need to do the following:对于 function 的应用程序,我需要执行以下操作:
Here are my providers.这是我的提供者。
final firebaseAuthProvider = Provider<FirebaseAuth>((ref) => FirebaseAuth.instance);
final authStateChangeProvider = StreamProvider<User?>((ref) => ref.watch(firebaseAuthProvider).authStateChanges());
final firestoreDatabaseProvider = Provider<FirestoreDatabase?>((ref) {
final auth = ref.watch(authStateChangeProvider);
if (auth.asData?.value?.uid != null) {
return FirestoreDatabase(uid: auth.asData!.value!.uid);
}
return null;
});
final firestoreUserChangeProvider = StreamProvider<FirestoreUser?>((ref) {
return ref.watch(firestoreDatabaseProvider)!.getFirestoreUser();
});
final apiServiceProvider = Provider<ApiService?>((ref) {
final auth = ref.watch(authStateChangeProvider);
if (auth.asData?.value?.uid != null) {
return ApiService(uid: auth.asData!.value!.uid);
}
return null;
});
To maintain the state of ProfileUser from the api I'm using StateNotifier and it's not working properly.为了维护来自 api 的ProfileUser的 state,我正在使用StateNotifier ,但它无法正常工作。
The error I'm getting is Unhandled Exception: Bad state: Tried to use ProfileUserStateNotifier after dispose
was called.我得到的错误是Unhandled Exception: Bad state: Tried to use ProfileUserStateNotifier after
dispose
被调用。
class ProfileUserStateNotifier extends StateNotifier<ProfileUser?> {
ApiService? _apiService;
ProfileUserStateNotifier(this._apiService) : super(new ProfileUser()) {
load();
}
void load() async {
var profileUser = await _apiService!.getProfile();
state = profileUser;
}
}
final profileNotifier =
StateNotifierProvider<ProfileUserStateNotifier, ProfileUser?>((ref) {
final firestoreUser = ref.watch(firestoreUserChangeProvider);
final firestoreDb = ref.read(firestoreDatabaseProvider);
firestoreUser.whenData((value) {
if (value!.syncRequired!) {
firestoreDb!.stopSync();
}
});
return ProfileUserStateNotifier(ref.read(apiServiceProvider));
});
firestore_database.dart firestore_database.dart
Stream<FirestoreUser> getFirestoreUser() {
return ref.doc(uid).snapshots().map((value) => FirestoreUser.fromJson(value.data() as Map<dynamic, dynamic>));
}
api_service.dart api_service.dart
Future<ProfileUser?> getProfile() async {
//call api end point
return profileUser;
}
How can I make sure that I have uid from the auth provider, FirestoreUser initiated and ProfileUser object before any other action take place?在进行任何其他操作之前,如何确保我已从身份验证提供程序、FirestoreUser 启动和 ProfileUser object 获得 uid?
Also, I'm not sure if I'm using the StateNotifer properly in my home screen as I'm checking for null and displaying progress indicator.另外,我不确定我是否在主屏幕中正确使用了StateNotifer ,因为我正在检查 null 并显示进度指示器。 What if the api call returns null in that case my home screen will be stuck in progress indicator.
如果 api 调用返回 null 在这种情况下我的主屏幕将卡在进度指示器中怎么办。
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Consumer(
builder: (context, watch, child) {
var profile = ref.watch(profileNotifier);
if (profile!.username == null) {
return Scaffold(body: Center(child:CircularProgressIndicator()));
} else {
return Scaffold(body: Center(child: Text(profile.username!)));
}
}),
);
}
Sorry, I'm new to Flutter and Riverpod so any code reference or link to tutorials to solve the issue I'm having would be highly appreciated.抱歉,我是 Flutter 和 Riverpod 的新手,所以任何代码参考或教程链接来解决我遇到的问题将不胜感激。
Managed to solve the problem but api is getting called twice when the firestore document is updated.设法解决了这个问题,但是当 Firestore 文档更新时,api 被调用了两次。
final profileAsyncController =
StateNotifierProvider<ProfileAsyncNotifier, AsyncValue<ProfileUser?>>(
(ref) => ProfileAsyncNotifier(ref));
class ProfileAsyncNotifier extends StateNotifier<AsyncValue<ProfileUser?>> {
ProfileAsyncNotifier(this.ref) : super(AsyncLoading()) {
_init();
}
final Ref ref;
void _init() async {
final firestoreUser = ref.watch(firestoreUserChangeProvider);
var profile = await ref.read(apiServiceProvider)!.getProfile();
state = AsyncData(profile);
final firestoreDb = ref.read(firestoreDatabaseProvider);
firestoreUser.whenData((value) {
if (value!.syncRequired!) {
firestoreDb!.stopSync();
}
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.