如何通过不同的页面(上下文)共享来自streambuilder的提供者数据 [英] How to share provider data from streambuilder via different pages (contextes)

查看:75
本文介绍了如何通过不同的页面(上下文)共享来自streambuilder的提供者数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在小部件上实时获取来自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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆