gpt4 book ai didi

Flutter:StreamProvider 的奇怪行为,使用不完整数据重建的小部件

转载 作者:行者123 更新时间:2023-12-05 07:02:07 29 4
gpt4 key购买 nike

我从 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);
}
}

}

这是 Firestore 中的统计数据 Map: stats map

最佳答案

虽然 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com