首页 > 解决方案 > 使用 Provider 向整个 Flutter 模块全局提供 BLoC

问题描述

https://pub.dev/packages/provider

我可以使用 Provider 在没有 MaterialApp 的情况下为树下的所有小部件全局提供块吗?我尝试向页面提供 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 上找到

标签: flutterprovider

解决方案


您可以通过使用 a 的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 和使用 builder 的区别在于 home 子树被插入到Navigator下面的应用程序中。

建设者

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

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

这就是为什么这很有效:

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

在上面的这个设置中,位于小部件Provider的顶部。Navigator

这不会:

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

_someBloc只有小部件可以访问FirstPage

希望这可以帮助。


推荐阅读