使用 Provider 向整个 Flutter 模块全局提供 BLoC

Posted

技术标签:

【中文标题】使用 Provider 向整个 Flutter 模块全局提供 BLoC【英文标题】:Use Provider to provide BLoCs globally to whole flutter module 【发布时间】:2020-06-11 16:10:02 【问题描述】:

https://pub.dev/packages/provider

在没有 MaterialApp 的情况下,我可以使用 Provider 为树下的所有小部件全局提供块吗?我尝试向页面提供 BLoC,但是当我导航到下一页时,找不到 BloC。那么我应该在导航到新页面时提供它,还是有解决方案可以在没有 MaterialApp 的情况下在全球范围内提供它?

目前我正在这样做

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

这种方法有效,所有页面都可以访问提供的 BLoC。

但是如果使用这种方法

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

MyPage2、MyPage3 找不到提供的 BLoC。 BLoC 只能在 MyPage1 上找到

【问题讨论】:

【参考方案1】:

您可以通过使用MaterialAppbuilder 属性来实现此目的。

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 和使用 builder 的区别在于 home 子树被插入到应用程序下面导航器中。

建造者

...从构建器返回的小部件插入上方应用的导航器(如果有)。

如果您希望在所有路线上提供您的“区块”,则必须在 Navigator 小部件上方提供这些。

这就是为什么这很简单:

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

在上述设置中,Provider 位于 Navigator 小部件之上。

这不是:

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

_someBloc 只能由 FirstPage 小部件访问。

希望这会有所帮助。

【讨论】:

以上是关于使用 Provider 向整个 Flutter 模块全局提供 BLoC的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 应用程序 Multi Provider 和相互依赖的 Stream Providers

Flutter Provider-重建列表项而不是列表视图

Flutter Provider 重建不必要的小部件

Flutter:如何用 Provider 播放动画?

flutter_bloc/provider RepositoryProvider vs Provider

在 Flutter 中,是不是可以使用 Provider 创建监听函数