skip to Main Content

I am trying to use bloc in my code for firestore database

HandleSubscription method

  void handleSubscription() {

    context.read<SubscriptionBloc>().saveNewSubscription("123", "abc");
   
  }

Widget build:

    @override
      Widget build(BuildContext context) {
       handleSubscription();

       return Scaffold(
      ...
    );
    }

I have SubscriptionBloc code but I don’t want to share as my problem is not related with this code.

I am getting this error:

Exception has occurred. ProviderNotFoundException (Error: Could not
find the correct Provider above this ArticleDetails
Widget

This happens because you used a BuildContext that does not include
the provider of your choice. There are a few common scenarios:

  • You added a new provider in your main.dart and performed a hot-reload. To fix, perform a hot-restart.

  • The provider you are trying to read is in a different route.

    Providers are "scoped". So if you insert of provider inside a route,
    then other routes will not be able to access that provider.

  • You used a BuildContext that is an ancestor of the provider you are trying to read.

    Make sure that ArticleDetails is under your
    MultiProvider/Provider. This usually happens when
    you are creating a provider and trying to read it immediately.

    For example, instead of:

      return Provider<Example>(
        create: (_) => Example(),
        // Will throw a ProviderNotFoundError, because `context` is associated
        // to the widget that is the parent of `Provider<Example>`
        child: Text(context.watch<Example>().toString()),
      );   }   ```
    
    consider using `builder` like so:
    
    ```   Widget build(BuildContext context) {
      return Provider<Example>(
        create: (_) => Example(),
        // we use `builder` to obtain a new `BuildContext` that has access to the provider
        builder: (context, child) {
          // No longer throws
          return Text(context.watch<Example>().toString());
        }
      );   }   ```
    
    

If none of these solutions work, consider asking for help on
StackOverflow: https://stackoverflow.com/questions/tagged/flutter )

2

Answers


  1. Make sure that the BuildContext used in handleSubscription() actually has access to SubscriptionBloc.

    I.e., you are trying to read a provider as soon as the widget builds. Consider deferring this to a later lifecycle method like didChangeDependencies or utilize a Builder widget to make sure the context you are using is a descendant of your provider.


    Builder approach:

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            handleSubscription();
            return // Rest of your UI
          },
        ),
      );
    }
    

    That Builder would create a new BuildContext that is a direct child of Scaffold, which should ideally be under your Provider<SubscriptionBloc> if you have structured your widget tree correctly.


    didChangeDependencies method approach:

    That method is called when a dependency of the State object changes.
    In your case, if your widget relies on an InheritedWidget (which is what Provider uses under the hood), didChangeDependencies is called whenever that inherited widget is updated.

    class YourWidget extends StatefulWidget {
      @override
      _YourWidgetState createState() => _YourWidgetState();
    }
    
    class _YourWidgetState extends State<YourWidget> {
      
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        handleSubscription();
      }
    
      void handleSubscription() {
        final bloc = Provider.of<SubscriptionBloc>(context, listen: false);
        bloc.saveNewSubscription("123", "abc");
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          // Your UI here
        );
      }
    }
    

    The handleSubscription method is moved into didChangeDependencies.
    The Provider.of<SubscriptionBloc>(context, listen: false) call fetches the SubscriptionBloc from the nearest ancestor in the widget tree. Since didChangeDependencies is called after initState and every time the widget rebuilds due to a change in an InheritedWidget, it is generally a safe place to access your Provider.

    That approach avoids accessing the Provider directly within the build method, giving the widget a chance to complete its initial build process.

    Login or Signup to reply.
  2. the error says the provider not found means you haven’t provided the provider above the widget

    Suppose your widget/screen is ArticleDetails in which you’re calling handleSubscription method, so what have you to do is wrap your ArticleDetails Widget/Screen with BlocProvider which will provide the scope of SubscriptionBloc to ArticleDetails. For example

    const BlocProvider(
        create: (context) => SubscriptionBloc(),
        child: ArticleDetails(),
    ),
    

    And the Article widget is

    class ArticleDetails extends StatefulWidget {
      const ArticleDetails({super.key});
    
      @override
      State<ArticleDetails> createState() => _ArticleDetailsState();
    }
    
    class _ArticleDetailsState extends State<ArticleDetails> {
      @override
      void initState() {
        handleSubscription();
        super.initState();
      }
    
      void handleSubscription() {
        context.read<SubscriptionBloc>().saveNewSubscription("123", "abc");
      }
    
      @override
      Widget build(BuildContext context) {
        return const Placeholder();
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search