Используйте Provider для предоставления BLoC глобально всему модулю флаттера - PullRequest
0 голосов
/ 27 февраля 2020

https://pub.dev/packages/provider

Могу ли я использовать Provider для глобального предоставления блоков всем виджетам в дереве без MaterialApp? Я пытался предоставить BLo C странице, но при переходе на следующую страницу Blo C не обнаруживается. Так что мне следует предоставлять его всякий раз, когда я перехожу на новую страницу, или есть решение предоставить его глобально без MaterialApp?

В настоящее время я делаю это следующим образом

Provider
|_MaterialApp
  |_MyPage1 (from which you can navigate to MyPage2...3)

Это подход работает, и все страницы могут получить доступ при условии BLo C.

Но если использовать этот подход

Provider
  |_MyPage1 (from which you can navigate to MyPage2...3)

MyPage2, MyPage3 не сможет найти предоставленный BLo C. BLo C можно найти только на MyPage1

1 Ответ

0 голосов
/ 07 марта 2020

Этого можно добиться, используя свойство builder MaterialApp.

lib / main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class SomeBloc {
  final String someValue;

  SomeBloc(this.someValue);

  void dispose() {}
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  SomeBloc _someBloc = SomeBloc("someValue");

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      builder: (context, widget) => Provider<SomeBloc>(
        create: (_) => _someBloc,
        dispose: (_, bloc) => bloc.dispose(),
        child: widget,
      ),
      initialRoute: '/first-page',
      routes: <String, WidgetBuilder>{
        '/first-page': (context) => FirstPage(),
        '/second-page': (context) => SecondPage(),
      },
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SomeBloc _someBloc = Provider.of<SomeBloc>(context);
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_someBloc.someValue),
            RaisedButton(
              child: Text("Open second page"),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (_) => SecondPage(),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SomeBloc _someBloc = Provider.of<SomeBloc>(context);

    return Scaffold(
      body: Center(
        child: Text(_someBloc.someValue),
      ),
    );
  }
}

Согласно документации,

home

Разница между использованием home и использованием builder заключается в том, что поддерево home вставляется в приложение ниже a Navigator.

builder

... виджет, возвращаемый из Builder, вставляется над навигатором приложения (если есть).

Если вы хотите, чтобы ваши «блоки» предоставлялись на всех ваших маршрутах, вы должны предоставить их выше виджета Navigator.

Вот почему это просто работает:

return Provider(
  create: (_) => _someBloc,
  child: MaterialApp(
    home: FirstPage(),
  ),
);

В приведенной выше настройке Provider находится над виджетом Navigator.

И это не так:

return MaterialApp(
  home: Provider(
    create: (_) => _someBloc,
    child: FirstPage(),
  ),
);

_someBloc будет доступен только для виджета FirstPage.

Надеюсь, это поможет.

...