简体   繁体   English

riverpod state 未更新

[英]riverpod state not updating

(Update at the end of the post) I want to add my normal firebase auth with additional user information. (在帖子末尾更新)我想添加我的普通 firebase 身份验证和其他用户信息。 In this example, name and goal calories.在这个例子中,名称和目标卡路里。 For that, I created this register function:为此,我创建了这个寄存器 function:

 Future<void> signUpWithEmailAndPassword(String email, String password, BuildContext context, WidgetRef ref, widget) async {
    FocusManager.instance.primaryFocus?.unfocus();
    try {
      await auth.createUserWithEmailAndPassword(email: email, password: password);
      ref.read(isUp.notifier).state = false;
      ref.read(writeItemViewModelProvider).setInitValue();
    } on FirebaseAuthException catch (e) {
    

the function setInitValue() looks like this: function setInitValue()看起来像这样:

class FirestoreDb extends ChangeNotifier {
   Future<void> setInitValue() async {
    await firebaseFirestore.collection('/users/${auth.currentUser!.uid}/UserInfo').doc(auth.currentUser!.uid).set({
      'name': null,
      'calories': null,
    });
  }
}

Here seems to work everything fine.这里似乎一切正常。 Inside firestore a file gets created and my user also.在 firestore 中创建了一个文件,我的用户也被创建了。 Without this additional user infos my auth works also fine.如果没有这些额外的用户信息,我的身份验证也可以正常工作。 So I think there is a problem with my stream of the user information.所以我认为我的stream的用户信息有问题。 Because: I have to check if the registert user has already added information or not.因为:我必须检查注册用户是否已经添加了信息。 I do this with a second.when function:我用 second.when function 来做这个:

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final authState = ref.watch(authStateProvider);
    final watcher = ref.watch(itemsProvider);
    return authState.when(
        data: (data) {
          if (data != null) {
            return watcher.when(data: (calo) {
              if (calo.first.calories != null) {
                return const RootPage();
              } else {
                return UserInformation();
              }
            }, error: (e, trace) => ErrorScreen(e, trace),  loading: () => const LoadingScreen());

the first.when function is for the auth, here seems to be no problem, but the secons is strange. first.when function 是给auth的,这里好像没问题,但是秒就奇怪了。 When I login first time, it says bad state. From now on, every time I register with a different account, I only get the old data from the previous account until I hot restart.第一次登录的时候提示bad state,以后每次换个账号注册,热重启之前只能获取之前账号的旧数据。 After the user information, you get to this page:输入用户信息后,您将进入此页面:

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final streamData = ref.watch(itemsProvider);
    return Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      appBar: AppBar(toolbarHeight: 0, backgroundColor: Colors.transparent),
      resizeToAvoidBottomInset: false,
      body: streamData.when(  data: (calo) {
        return Text(calo.first.calories.toString());
      }, error: (e, trace) => ErrorScreen(e, trace),  loading: () => const LoadingScreen())

    );
  }

where I can see that s old information until hot restart.在热重启之前,我可以在那里看到旧信息。

So something with my stream is not updating the state correctly.所以我的 stream 没有正确更新 state。 When I wrap delete the.when function and use a Streambuilder listening to the stream directly everything works.当我包装删除 the.when function 并使用 Streambuilder 直接监听 stream 时一切正常。

Here is my itemsProvider:这是我的项目提供者:

final itemsProvider = StreamProvider<List<UsersModel>>(
      (ref) => ref.read(itemRepositoryProvider).itemsStream,
);

final itemRepositoryProvider = Provider((ref) => ReadData());

class ReadData{
  Stream<List<UsersModel>> get itemsStream {
    return firebaseFirestore.collection('/users/${auth.currentUser!.uid}/UserInfo').snapshots().map((QuerySnapshot query) {
      List<UsersModel> user = [];
      for (var usersIter in query.docs) {
        final usersModel = UsersModel.fromDocumentSnapshot(documentSnapshot: usersIter);
        user.add(usersModel);
      }
      return user;
    });
  }
}

I check with debugging and "print points" the way of the compiler and recognised the problem but have no answer why the compiler do this:我检查了调试和“打印点”编译器的方式并识别了问题但没有回答为什么编译器这样做:

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    print("inside UserInfoBuild");
    final watcher = ref.watch(itemsProvider);
    return watcher.when(data: (userInfoData) {
      print("inside AsyncValue<List<UsersModel>>");
      if (userInfoData.first.calories != null) {
        return const RootPage();
      } else {
        return UserInformation(); [...]

declare provider:声明提供者:

final itemsProvider = StreamProvider<List<UsersModel>>(
      (ref) {
        print("inside stream provider");
        return ref.read(itemRepositoryProvider).itemsStream;
      },
);

so, my guess was that the print order should be:所以,我的猜测是打印顺序应该是:

I/flutter: inside UserInfoBuild
I/flutter: inside stream provider
I/flutter: inside AsyncValue<List<UsersModel>>

but its actually just:但它实际上只是:

I/flutter: inside UserInfoBuild
I/flutter: inside AsyncValue<List<UsersModel>>

so the compiler skips the final itemsProvider = StreamProvider.所以编译器会跳过最后的 itemsProvider = StreamProvider。 Just after a hot restart it executes the line of code在热重启之后,它会执行代码行

I think the key point is 'get' itemsStream.我认为关键点是“获取”itemsStream。 You have two ways to try.你有两种方法可以尝试。

// 1. // 1.

final itemsProvider = StreamProvider<List<UsersModel>>(
      (ref) => firebaseFirestore.collection('/users/${auth.currentUser!.uid}/UserInfo').snapshots().map((QuerySnapshot query) {
      List<UsersModel> user = [];
      for (var usersIter in query.docs) {
        final usersModel = UsersModel.fromDocumentSnapshot(documentSnapshot: usersIter);
        user.add(usersModel);
      }
      return user;
    }),
);

// 2. You can use StreamController to get data from firebaseFirestore.collection in ReadData class, and use a Stream variable to sync that value. // 2. 您可以使用 StreamController 从 ReadData class 中的 firebaseFirestore.collection 获取数据,并使用一个 Stream 变量来同步该值。 Update StreamProvider to the Stream variable.将 StreamProvider 更新为 Stream 变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM