3 votes

Le fournisseur de référentiel dans la bibliothèque flutter_bloc ne fournit pas le référentiel avec lorsqu'il pousse une nouvelle route

J'utilise la bibliothèque flutter_bloc pour architecturer mon application. En plus du BlocProvider, j'utilise le Repository Provider, car je vais utiliser un dépôt spécifique de manière extensive dans mon application. Mais j'ai un problème en ce qui concerne le contexte. Voici un extrait de mon code :

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

        },
      ),
    );
  }
}

Le bouton d'enregistrement se trouve dans le formulaire de connexion :

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

Question :

J'obtiens une erreur lorsque je clique sur le bouton d'enregistrement de mon formulaire de connexion qui se présente comme suit :

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))

Pourquoi est-ce que je reçois cette erreur ? Ce problème semble être résolu si je place le fournisseur de référentiel en tant qu'enfant du blocprovider et app en tant que fournisseur de référentiel enfant dans la fonction principale, puis en supprimant les différents fournisseurs de référentiel dans App(). Je suppose que le problème vient du fait que l'on pousse la route de la page matérielle à partir du bouton. Je ne pense pas comprendre comment le contexte ou le fournisseur fonctionne exactement dans Flutter. Je pensais que le provider recherchait l'arbre des widgets pour le dépôt/bloc, est-ce que le fait de pousser une route rompt d'une certaine manière cette continuité ?

7voto

GiancarloCode Points 609

Lorsque vous utilisez Navigator.of(context).push o Navigator.of(context).pushNamed le widget poussé n'est pas un enfant du widget qui appelle Navigator.of(context).push o Navigator.of(context).pushNamed ce widget est un enfant de l'instance la plus proche de Navigator qui entoure l'élément context Dans votre cas, le Navigator est créé par le MaterialApp Par conséquent, si vous souhaitez fournir le Repository o Bloc à différents routes , le Provider doit être un parent du Navigator Dans votre cas, il doit s'agir d'un parent de MaterialApp .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X