flutter - 使用 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 来不必要地获取数据。
解决方案
我想通了,在我的 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..."),
),
);
}
},
);
}
}
推荐阅读
- wordpress - 我在站点健康 Wordpress 中有错误
- javascript - 在屏幕 OrderWidget POS odoo-12 中覆盖 set_value 函数
- php - 此处映射“这些凭据不授权访问”
- javascript - 在 HTML 中使用 document.getElementById 清除段落
- python - 使用python将数据从文件加载到oracle表
- c - C:为什么使用寄存器会被认为是不好的做法?
- java - Java - 如何使用 Mockito 模拟静态块
- javascript - puppeteer 无法在 CSS 网格中选择
- excel - 我只想通过文本使用正则表达式获取数值
- api - 如何将 JSON 输入正文参数保存到 POSTMAN 中的全局变量(检查图像)