如何通过不同的页面(上下文)共享来自streambuilder的提供者数据 [英] How to share provider data from streambuilder via different pages (contextes)
问题描述
我想在小部件上实时获取来自Firebase的数据.当我尝试使用StreamProvider
然后再使用Navigator.push()
时,推入式小部件无法使用Provider.of(context)
获取值.
I want to have data from firebase in realtime on a widget. When I try to use a StreamProvider
and then use Navigator.push()
, the pushed widget can't get the value with Provider.of(context)
.
我尝试将StreamProvider
用作MaterialApp
的父级.这可行,但是需要登录用户才能使Stream获得用户的数据.
我也尝试使用ScopedModel
.这也可以,但是我不知道这是否是最好的方法.
I tried putting the StreamProvider
as the parent of MaterialApp
. This works but the user needs to be logged in order for the Stream to get the data of the user.
I also tried using a ScopedModel
. This works as well, but I don't know if this is the best approach to do this.
我想避免使用全局StreamProvider
,并希望有一个有效的解决方案(尽可能少地读取来自Firebase的内容)
I would like to avoid using a global StreamProvider
and would like to have an efficient solution (as little reads from firebase as possible)
main.dart
void main() => runApp(MyApp());
final GlobalKey<ScaffoldState> mainScaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey<ScaffoldState> authScaffoldKey = GlobalKey<ScaffoldState>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel<ScreenModel>(
model: ScreenModel(),
child: MultiProvider(
providers: [
StreamProvider<User>.value(value: authService.userDoc,),
StreamProvider<bool>.value(value: authService.loading.asBroadcastStream())
],
child: MaterialApp(
title: "ListAssist",
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: MainApp()
),
)
);
}
}
class MainApp extends StatefulWidget {
@override
_MainAppState createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
@override
Widget build(BuildContext context) {
User user = Provider.of<User>(context);
bool loading = Provider.of<bool>(context);
return AnimatedSwitcher(
duration: Duration(milliseconds: 600),
child: user != null ?
StreamProvider<Group>.value(
value: databaseService.streamGroupsFromUser(),
child: Scaffold(
key: mainScaffoldKey,
body: Body(),
drawer: Sidebar(),
),
) : Scaffold(
key: authScaffoldKey,
body: AnimatedSwitcher(
duration: Duration(milliseconds: 600),
child: loading ? SpinKitDoubleBounce(color: Colors.blueAccent) : AuthenticationPage(),
),
resizeToAvoidBottomInset: false,
)
);
}
}
class Body extends StatefulWidget {
createState() => _Body();
}
class _Body extends State<Body> {
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<ScreenModel>(
builder: (context, child, model) => model.screen
);
}
}
在补充工具栏中,我可以更改为GroupView
,而Provider
仍然有效.
In the Sidebar I can change to GroupView
and the Provider
still works.
sidebar.dart
(重要部分)
onTap: () {
ScreenModel.of(context).setScreen(GroupView(), "Gruppen");
Navigator.pop(context);
},
GroupView
中包含GroupItem
group-item.dart
(重要部分)
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return GroupDetail();
}),
)
当我尝试在GroupDetail
中使用Group group = Provider.of<Group>(context);
或它的子控件时,它说找不到context
的任何Provider
.
When I try to use Group group = Provider.of<Group>(context);
in GroupDetail
or a child widget of it, it says that it cannot find any Provider
for the context
.
这是存储库.
推荐答案
我想出了方法.我使用了一个名为custom_navigator
的软件包.
I figured out how to do it. I used a package called custom_navigator
.
在sidebar.dart
中,当有人将组视图更改为以下内容时,我将孩子更改了:
In sidebar.dart
I changed the child when someone changes to the group view to the following:
StreamProvider<Group>.value(
value: databaseService.streamGroupsFromUser(user.uid),
child: CustomNavigator(
home: GroupView(),
pageRoute: PageRoutes.materialPageRoute,
)
)
使用CustomNavigator
,即使在Navigator.push()
之后,我仍然可以使用Provider.of<Group>(context)
来获取数据.
With the CustomNavigator
I can still use Provider.of<Group>(context)
to get the data, even after a Navigator.push()
.
这篇关于如何通过不同的页面(上下文)共享来自streambuilder的提供者数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!