Как поделиться данными провайдера из streambuilder через разные страницы (контексты) - PullRequest
6 голосов
/ 22 октября 2019

Я хочу, чтобы данные из Firebase в режиме реального времени на виджете. Когда я пытаюсь использовать StreamProvider, а затем Navigator.push(), выдвинутый виджет не может получить значение с Provider.of(context).

Я попытался указать StreamProvider в качестве родителя MaterialApp. Это работает, но пользователь должен войти в систему, чтобы Stream мог получить данные пользователя. Я также пытался использовать ScopedModel. Это также работает, но я не знаю, является ли это наилучшим подходом для этого.

Я хотел бы избежать использования глобального StreamProvider и хотел бы иметь эффективное решение (так как мало читаетиз пожарной базы, насколько это возможно)

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 все еще работает.

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();
  }),
)

Когда я пытаюсь использоватьGroup group = Provider.of<Group>(context); в GroupDetail или дочернем виджете, он говорит, что не может найти Provider для context.

Здесь находится репозиторий .

1 Ответ

1 голос
/ 30 октября 2019

Я разобрался, как это сделать. Я использовал пакет под названием custom_navigator.

В sidebar.dart Я изменил дочернего элемента, когда кто-то переключается в групповое представление, на следующее:

StreamProvider<Group>.value(
  value: databaseService.streamGroupsFromUser(user.uid),
  child: CustomNavigator(
    home: GroupView(),
    pageRoute: PageRoutes.materialPageRoute,
  )
)

С помощью CustomNavigator я могупо-прежнему использовать Provider.of<Group>(context) для получения данных, даже после Navigator.push().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...