首页 > 解决方案 > 使用 Firestore 在 Flutter 中加载配置文件数据的最佳方式是什么?

问题描述

我正在尝试使用 Firestore 加载配置文件数据。我不想每次点击主页时都重新加载数据。

我想将此数据存储在类对象中,然后有一个刷新功能,用户可以在第一次初始化配置文件数据后手动调用。我想在调用“主页”小部件时执行此操作,传递我的“ProfileModel”的快照,但它会以相同的方式持续加载这些数据吗?

这是为所选索引调用的导航栏小部件类

  class SelectedNavigationBarItem extends StatelessWidget {
  FirebaseAuth auth;
  FirebaseFirestore firestore;
  final int currentIndex;
  bool hasBeenWelcomed = false;
  @override
  SelectedNavigationBarItem(
      {@required this.auth, @required this.firestore, this.currentIndex});

  @override
  Widget build(BuildContext context) {
    List<Widget> _widgetOptions = <Widget>[
      HomeBarWelcome(
          auth: this.auth,
          firestore: this.firestore,
          welcomed: hasBeenWelcomed),
      Text("PlaceHolder1"),
      Text("Placeholder2"),
      Text("Placeholder3"),
    ];
    return _widgetOptions.elementAt(this.currentIndex);
  }
}

我正在考虑一种使用 FutureBuilder 或 StreamBuilder 将配置文件数据快照传递给我拥有的 HomePage 类的方法。然后从那里,我会将该快照向下传递到小部件树,但如果我在我的第一个小部件中执行此操作,由 runApp() 调用的小部件,它会持续加载配置文件数据并继续调用 Firestore 以获取配置文件数据吗?或者它会运行一次,然后放在 HomePage 类中,该类将在第一次 runApp() 调用中返回?

我想我只是在问小部件是如何被调用的?runApp() 是否被连续调用,然后每次调用都会遍历小部件路径?或者它是否被调用一次,然后 Widget 类从那里处理 Flutter 应用程序的状态,并且每个 Widget 类根据该 Widget 类中调用的下一个小部件来控制状态?
抱歉,我确信这是一个相当混乱的帖子。但我只是在寻找加载这些数据的正确方法,因为我不希望重复调用 Firestore 来不必要地获取数据。

标签: fluttergoogle-cloud-firestorefirebase-authenticationflutter-layout

解决方案


我想通了,在我的 MaterialApp 调用的身份验证包装器中,我使用了带有嵌套 FutureBuilders 的 StreamBuilder 来解决我的问题。在此之后,我只是通过我的小部件树传递了变量。

我觉得好像有更好的方法可以做到这一点,但我还没有答案。所以我将使用它,因为它有效。

这是我的 _AuthWrapperState 类:

class _AuthWrapperState extends State<AuthenticationWrapper> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<ProfileModel> _getProfile() async {
    return await Database(_firestore).getProfile(uid: _auth.currentUser.uid);
  }

  Future<SharedPreferences> _getPrefs() async {
    return await SharedPreferences.getInstance();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: AuthService(auth: _auth, firestore: _firestore).user,
      builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
        if (snapshot.connectionState == ConnectionState.active) {
          if (snapshot.data?.uid == null) {
            return SignIn(auth: _auth, firestore: _firestore);
          } else {
            return FutureBuilder(
                future: _getProfile(),
                builder: (builder, AsyncSnapshot<ProfileModel> snapshot) {
                  if (snapshot.hasData) {
                    ProfileModel profileModel = snapshot.data;
                    return FutureBuilder(
                        future: _getPrefs(),
                        builder: (context,
                            AsyncSnapshot<SharedPreferences> snapshot) {
                          if (snapshot.hasData) {
                            return Home(
                              auth: _auth,
                              firestore: _firestore,
                              profileModel: profileModel,
                              sharedPrefs: snapshot.data,
                            );
                          } else {
                            return const Scaffold(
                              body: CircularProgressIndicator(),
                            );
                          }
                        });
                  } else {
                    return const Scaffold(
                        body: Center(child: CircularProgressIndicator()));
                  }
                });
          }
        } else {
          return const Scaffold(
            body: Center(
              child: Text("Loading..."),
            ),
          );
        }
      },
    );
  }
}

推荐阅读