- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从 StreamProvider 获取的数据不完整。
下一个最小的小部件树重现了我的问题:选项卡式屏幕上的 SreamProvider。
我的用户对象包含多个值(以及其他属性)的映射,我通过调用 final user = Provider.of<User>(context);
将这些值用于选项卡式 View 的一个屏幕。在build()
里面方法以便在应用程序启动或完全重建(即热重载)时在此屏幕中获取这些值。
问题:每当我切换标签并返回此标签时,build()
使用 final user = Provider.of<User>(context);
仅调用一次方法返回用户的不完整副本:缺少某些数据(用户对象内 map 的某些属性)和 build()
永远不会再次调用来完成数据(假设 StreamProvider 应该在某个时候返回完整的对象,可能会导致一些重建。结果:一些数据丢失并且无法构建 Screen 的一些小部件。
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final firebaseUser = Provider.of<FirebaseUser>(context);
// return either Home or Authenticate widget:
if (firebaseUser == null) {
return WelcomeScreen();
} else {
return StreamProvider<User>.value(
value: FirestoreService(uid: firebaseUser.uid).user,
child: TabsWrapper(),
);
}
}
}
class TabsWrapper extends StatefulWidget {
final int initialIndex;
TabsWrapper({this.initialIndex: 0});
@override
_TabsWrapperState createState() => _TabsWrapperState();
}
class _TabsWrapperState extends State<TabsWrapper> with TickerProviderStateMixin {
TabController tabController;
@override
void initState() {
super.initState();
tabController = TabController(vsync: this, length: choices.length);
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: widget.initialIndex,
length: 3,
child: Scaffold(
backgroundColor: lightBlue,
bottomNavigationBar: TabBar(
controller: tabController,
labelStyle: navi.copyWith(color: darkBlue),
unselectedLabelColor: darkBlue,
labelColor: darkBlue,
indicatorColor: darkBlue,
tabs: choices.map((TabScreen choice) {
return Tab(
text: choice.title,
icon: Icon(choice.icon, color: darkBlue),
);
}).toList(),
),
body: TabBarView(
controller: tabController,
children: <Widget>[
FirstScreen(),
SecondScreen(),
ThirdScreen(),
],
),
),
);
}
}
有问题的屏幕 (FirstScreen):
class FirstScreen extends StatelessWidget {
final TabController tabController;
final User user;
FirstScreen ();
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print('**************************************** ${user.stats}'); //Here I can see the problem
return SomeBigWidget(user: user);
}
}
print(${user.stats}) 显示了不完整的 map (统计数据)和 build()
永远不会再次调用(使用剩余数据),因此 User 对象仍然不完整。它仅在重新加载或启动应用程序时被调用两次(数据与完整对象一起返回)。
欢迎任何解决方案!
PD:我找到了一种更简单的方法来重现这种情况。无需更改标签:
内部FirstScreen()
我有一列 StatelessWidgets。如果我调用 Provider.of<User>(context)
在其中一个中,我得到了该对象的不完整版本。 user.stats
map 具有通过 Provider.of 访问它时所具有的键值对的一半。上面的一些小部件。
这是从 Firebase 更新流的方式。 (每次都创建对象):
Stream<User> get user {
Stream<User> userStream = usersCollection.document(uid).snapshots().map((s) => User.fromSnapshot(s));
return userStream;
}
我还有updateShouldNotify = (_,__) => true;
用户模型:
class User {
String uid;
String name;
String country;
Map stats;
User.fromUID({@required this.uid});
User.fromSnapshot(DocumentSnapshot snapshot)
: uid = snapshot.documentID,
name = snapshot.data['name'] ?? '',
country = snapshot.data['country'] {
try {
stats = snapshot.data['stats'] ?? {};
} catch (e) {
print('[User.fromSnapshot] Exception building user from snapshot');
print(e);
}
}
}
最佳答案
虽然 firebase 确实允许您使用 map 作为您使用的类型,但我认为在这种情况下这不是您的最佳选择,因为它看起来很困惑。
您的问题有多种解决方案。
我认为最好的方法是将您的用户集合并排创建一个名为“stats”的集合,并让每个 stat 的 docid = 具有该统计信息的用户的 userid,这使您将来的查询更容易。
在此之后,您可以使用您已经使用过的方法来获取统计数据,就像获取用户一样。
class Stat {
String statid;
int avg;
int avg_score;
List<int> last_day;
int n_samples;
int total_score;
int words;
Stat.fromSnapshot(DocumentSnapshot snapshot){
statid = snapshot.documentID,
avg = snapshot.data['average'] ?? '',
//rest of data
}
}
也许您需要的简单解决方案是将 User 类中的 map 更改为此。
Map<String, dynamic> stats = Map<String, dynamic>();
删除 try 和 catch block ,然后您应该能够像这样访问您的数据 user.stats['average'];
希望这会有所帮助,当我实际可以在模拟器中进行测试时,我会更新我的答案,但如果您尝试了并且成功了,请告诉我。
关于Flutter:StreamProvider 的奇怪行为,使用不完整数据重建的小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63656437/
我正在使用 Google Cloud Firestore 作为 Flutter 应用程序的后端。目前我正在使用 StreamProvider 从云 firestore 构建数据流。现在,我需要维护 2
我正在尝试使用 StreamProvider(来自 this awesome package),但我一直在努力让特定的流工作。 我创建了一个 StreamController,我用它通过它的 Sink
我从 StreamProvider 获取的数据不完整。 下一个最小的小部件树重现了我的问题:选项卡式屏幕上的 SreamProvider。 我的用户对象包含多个值(以及其他属性)的映射,我通过调用 f
目前,我们正在使用 Firebase 在我们的应用程序上实现简单的聊天。 我们使用 Riverpod 处理应用程序的启动和身份验证。 启动过程如下: @override Widget build(
我想知道是否有人可以告诉我如何实现 Flutter StreamProvider“catchError”属性? 下面的示例代码添加到: StreamProvider.value( initia
我是 flutter 的新手。我实现了这个示例应用程序以了解 SQLite 和提供程序状态管理。这是一个简单的任务管理系统。我使用 MOOR 来处理 SQLite 数据库。我遇到的问题是任务列表在添加
我使用 StreamProvider将图像提供给其他应用程序。一切正常,但有一种情况除外:当我尝试将多张图像共享到我的三星 S6 设备(Android 5.1.1)上的消息传递应用程序时,消息传递应用
StreamProvider.value 使用相同的值多次构建小部件。 StreamProvider.value( value: FirebaseAuth.instance.onAuthS
我有一个像这样的 StreamBuilder: StreamBuilder>( stream: myDatabase.authInfosDao.watch(),
我正在 Flutter 中开发一个应用程序(我还是个新手),但遇到以下错误: Error: Could not find the correct Provider> above this Exerci
我有两个流: Stream FirebaseAuth.instance.onAuthStateChanged Stream userService.streamUser(String uid) 我的
当我尝试在 firestore 中获取不存在的数据时,我遇到了 StreamProvider 的问题。 Stream streamCollectedItem(String id,int categor
我有一个实现 firebase 身份验证的 flutter 应用程序。关注this后教程我的 main.dart 文件如下所示: class MyApp extends StatelessWidget
我有一个实现 firebase 身份验证的 flutter 应用程序。关注this后教程我的 main.dart 文件如下所示: class MyApp extends StatelessWidget
我正在使用 Flutter 开发一个应用程序,我正在使用 Cloud Firestore。是否有任何理由更喜欢 StreamBuilder 之间的一个和 StreamProvider ? 最佳答案 有
我正在尝试设置一个个人资料类型页面,用户可以在其中查看他们的信息,最终我将添加功能,以便他们可以更改他们的数据。我正在使用 Provider 访问 Firebase 流 它返回当前用户的 UID(这工
我试图通过将简单的 FireStore auth Provider 示例迁移到 RiverPod 来了解 RiverPod。 这是我的身份验证服务: import 'package:firebase_
有时我想我得到了提供者的逻辑,然后我被难住了几个小时试图做下面的事情。 我需要从 Firestore 集合流中获取连接 ID 列表。简单。 但是,我需要将此连接 ID 的流列表提供给另一个 fires
我注意到自从我使用 StreamProvider 添加一个新的 Stream 以来,我的读取请求显着增加。 ,我设法通过删除流和没有重复请求来确认这一点。但我似乎无法追查为什么它重复。 注意:代码运行
我正在尝试根据 Firebase 的身份验证状态创建一个简单的导航,但出于某种原因Provider.of(context)始终返回 null 作为小部件构建方法中的第一个值。所以我的应用程序总是导航到
我是一名优秀的程序员,十分优秀!