推送新路线时,flutter_bloc库中的存储库提供程序不提供存储库

时间:2019-09-25 17:25:50

标签: flutter dart bloc

我正在使用flutter_bloc库来构建我的应用程序。除了BlocProvider之外,我还使用存储库提供程序,因为我将在整个应用程序中广泛使用特定的存储库。但是我在上下文方面有一个问题。以下是我的代码段:

main.dart

void main() async {
  .......
  appRepository _appRepository = AppRepository();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) {
    runApp(
      BlocProvider(
        builder: (context) =>
            AuthenticationBloc(appRepository: _appRepository)..dispatch(AppStarted()),
        child: App(appRepository: _appRepository,),
      ),
    );
  });
}

class App extends StatelessWidget {

............
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (BuildContext context, AuthenticationState state) {
       .....
          if (state is AuthenticationUnauthenticated) {
            return SafeArea(
              top: false,
              bottom: false,
              child: RepositoryProvider(
                builder: (context) => _appRepository,
                child: LoginPage(firebaseMessaging: _firebaseMessaging),
              ),
            );
          }
      ......

        },
      ),
    );
  }
}
在登录表单中找到

注册按钮:

register_button.dart

class RegisterButton extends StatelessWidget {
  final FirebaseMessaging _firebaseMessaging;

  RegisterButton({
    Key key,
    @required FirebaseMessaging firebaseMessaging,
  })  : assert(firebaseMessaging != null),
        _firebaseMessaging = firebaseMessaging,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text("Don't have an account?", style: TextStyle(color: Colors.black)),
        SizedBox(width: 4.0),
        GestureDetector(
          child: Text("Register here!",
              style: TextStyle(
                  color: Color(0xFF585B8D), fontWeight: FontWeight.w500)),
          onTap: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (context) {
                return RegisterPage(
                  firebaseMessaging: _firebaseMessaging,
                );
              }),
            );
          },
        )
      ],
    );
  }

register_page.dart

class RegisterPage extends StatelessWidget {
  final FirebaseMessaging _firebaseMessaging;

  RegisterPage({
    Key key,
    @required FirebaseMessaging firebaseMessaging,
  })  : assert(firebaseMessaging != null),
        _firebaseMessaging = firebaseMessaging,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider(
        builder: (context) => RegisterBloc(
          appRepository: RepositoryProvider.of<AppRepository>(context),
          firebaseMessaging: _firebaseMessaging,
        ),
        child: RegisterForm(),
      ),
    );
  }
}

问题:

单击登录表单上的注册按钮时,出现以下错误:

No ancestor could be found starting from the context that was passed to RepositoryProvider.of<AppRepository>().

This can happen if:
1. The context you used comes from a widget above the RepositoryProvider.
2. You used MultiRepositoryProvider and didn't explicity provide the RepositoryProvider types.

Good: RepositoryProvider<AppRepository>(builder: (context) => AppRepository())
Bad: RepositoryProvider(builder: (context) => AppRepository()).

The context used was: BlocProvider<RegisterBloc>(dirty, state: _DelegateWidgetState#a87b2(lifecycle state: created))

为什么会出现此错误?如果在主函数中将存储库提供程序作为blocprovider的子级,将应用程序作为子存储库提供程序,然后在App()中删除单个存储库提供程序,则似乎可以解决此问题。我猜问题出在按下按钮上的材料页面路线。我认为我不了解上下文或提供程序在Flutter中的工作原理。我以为提供商会为存储库/块查找小部件树,推送路由是否会破坏这种连续性?

1 个答案:

答案 0 :(得分:2)

当您使用Navigator.of(context).pushNavigator.of(context).pushNamed时,推入的小部件不是调用Navigator.of(context).pushNavigator.of(context).pushNamed的小部件的子级,则此小部件是最近实例的子级包含给定Navigator的{​​{1}}中的contextNavigator创建,因此如果要提供MaterialApp或{{ 1}}与Repository不同,Bloc必须是routes的父级,在您的情况下,必须是Provider的父级。