简体   繁体   English

未处理的异常:错误 state:在调用“dispose”后尝试使用 StateNotifier

[英]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 的应用程序,我需要执行以下操作:

  • When a user is authenticated, I need retrieve a Firestore document (FirestoreUser) as a stream (document matched on auth uid).当用户通过身份验证时,我需要将 Firestore 文档(FirestoreUser)检索为 stream(在 auth uid 上匹配的文档)。
  • Make an api call (not firestore) to retrieve ProfileUser model by passing uid as parameter which will be used throughout the app.进行 api 调用(不是 firestore)通过传递 uid 作为参数来检索ProfileUser model,该参数将在整个应用程序中使用。
  • Firestore document has a field called sync_required , if this value is set to true then make api call and refresh the UI and also set the sync_required to false . Firestore 文档有一个名为sync_required的字段,如果此值设置为true ,则调用 api 并刷新 UI 并将sync_required设置为false The purpose of this firestore document is to keep the Api data in sync inside the app.此 Firestore 文档的目的是使 Api 数据在应用程序内保持同步。
  • If the ProfileUser is updated within the app, the UI should reflect the changes and also call another api endpoint to update the source data.如果ProfileUser在应用程序中更新,UI 应反映更改并调用另一个 api 端点来更新源数据。

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.

相关问题 错误:flutter/lib/ui/ui_dart_state.cc(209) 未处理的异常:在 dispose() 之后调用 setState() - ERROR:flutter/lib/ui/ui_dart_state.cc(209) Unhandled Exception: setState() called after dispose() 未处理的异常:错误 state:无元素 - Unhandled Exception: Bad state: No element 未处理的异常:使用 Firebase 实时数据库聊天功能在 dispose() 之后调用 setState() - Unhandled Exception: setState() called after dispose() with Firebase Realtime Database chat feature Flutter Firebase 查询快照错误:“未处理的异常:错误状态:无元素” - Flutter firebase query snapshot error: "Unhandled Exception: Bad state: No element" Flutter:未处理的异常:错误 state:DocumentSnapshotPlatform 中不存在字段 - Flutter: Unhandled Exception: Bad state: field does not exist within the DocumentSnapshotPlatform 如何修复“未处理的异常:错误的 state:无法在 DocumentSnapshotPlatform 上获取不存在的字段”? - How to fix “Unhandled Exception: Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist”? 未处理的异常:NoSuchMethodError:在 null 上调用了 getter &#39;uid&#39; - Unhandled Exception: NoSuchMethodError: The getter 'uid' was called on null 颤振未处理的异常:NoSuchMethodError:方法&#39;then&#39;在null上被调用 - Flutter Unhandled Exception: NoSuchMethodError: The method 'then' was called on null 未处理的异常:NoSuchMethodError:在 null 上调用了方法“findAncestorStateOfType” - Unhandled Exception: NoSuchMethodError: The method 'findAncestorStateOfType' was called on null 错误:flutter/lib/ui/ui_dart_state.cc(177) 未处理的异常:NoSuchMethodError:在 null 上调用了方法“插入” - ERROR:flutter/lib/ui/ui_dart_state.cc(177) Unhandled Exception: NoSuchMethodError: The method 'insert' was called on null
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM