Home > Software engineering >  While using Bloc Listener I am getting an error ProviderNotFoundException (Error: Could not find the
While using Bloc Listener I am getting an error ProviderNotFoundException (Error: Could not find the

Time:06-11

I am learning bloc and was making a todo app but while calling my bloc listener in addition to do screen it is throwing an error. Error is showing in Add To-Do Class

The exception has occurred. ProviderNotFoundException (Error: Could not find the correct Provider above this BlocListener<TodosBloc, TodosState> 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 BlocListener<TodosBloc, TodosState> is under your MultiProvider/Provider. This usually happens when you are creating a provider and trying to read it immediately.

  For example, instead of:

  ```
  Widget build(BuildContext context) {
    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
)

Here is my code...

Main.dart

import 'package:bloc_practise/blocs/todos/todos_bloc.dart';
import 'package:bloc_practise/todo_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'home_screen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Color(0xff000A1F),
        appBarTheme: AppBarTheme(
          color: Color(0xff000A1F),
        ),
      ),
      home: MultiBlocProvider(providers: [
        BlocProvider(
          create: (context) => TodosBloc()
            ..add(
              LoadTodo(
                todos: [
                  Todo(
                    id: '1',
                    task: 'Sample Todo 1',
                    description: 'This is a test Todo',
                  ),
                  Todo(
                    id: '2',
                    task: 'Sample Todo 2',
                    description: 'This is a test Todo',
                  ),
                ],
              ),
            ),
        )
      ], child: HomeScreen()),
    );
  }
}

HomeScreen.Dart

import 'package:bloc_practise/blocs/todos/todos_bloc.dart';
import 'package:bloc_practise/todo_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'add_todo_screen.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<TodosBloc, TodosState>(
      builder: (context, state) {
        if (state is TodosLoading) {
          return CircularProgressIndicator();
        }
        if (state is TodosLoaded) {
          return Scaffold(
            appBar: AppBar(
              title: Text('Bloc Pattern To Dos'),
              actions: [
                IconButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => AddToDo(),
                      ),
                    );
                  },
                  icon: Icon(
                    Icons.add,
                    color: Colors.white,
                  ),
                ),
              ],
            ),
            body: Padding(
              padding: EdgeInsets.all(8.0),
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      child: Text(
                        'Pending To Dos..',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                    ListView.builder(
                        shrinkWrap: true,
                        itemCount: state.todos.length,
                        itemBuilder: (context, index) {
                          return _todoCard(state.todos[index]);
                        })
                  ]),
            ),
          );
        } else {
          return Text('Something Went Wrong');
        }
      },
    );
  }
}

Card _todoCard(Todo todo) {
  return Card(
    margin: EdgeInsets.only(bottom: 8.0, top: 8),
    child: Padding(
      padding: const EdgeInsets.all(10.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            '#${todo.id}: ${todo.task}',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          Row(
            children: [
              IconButton(
                onPressed: () {},
                icon: Icon(
                  Icons.add_task,
                ),
              ),
              IconButton(
                onPressed: () {},
                icon: Icon(
                  Icons.cancel,
                ),
              ),
            ],
          )
        ],
      ),
    ),
  );
}

Add To Do Screen.Dart

import 'package:bloc_practise/blocs/todos/todos_bloc.dart';
import 'package:bloc_practise/todo_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class AddToDo extends StatelessWidget {
  TextEditingController controllerId = TextEditingController();
  TextEditingController controllerTask = TextEditingController();
  TextEditingController controllerDescription = TextEditingController();

  AddToDo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Add to Dos'),
      ),
      body: BlocListener<TodosBloc, TodosState>(
        listener: (context, state) {
          if (state is TodosLoaded) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text("To Do Added Successfuly"),
              ),
            );
          }
        },
        child: Card(
          child: Padding(
            padding: EdgeInsets.all(8.0),
            child: Column(
              children: [
                _inputField('ID', controllerId),
                _inputField('Task', controllerTask),
                _inputField('Description', controllerDescription),
                Builder(builder: (context) {
                  return ElevatedButton(
                    onPressed: () {
                      var todo = Todo(
                        id: controllerId.text,
                        task: controllerTask.text,
                        description: controllerDescription.text,
                      );
                      context.read<TodosBloc>().add(AddTodo(todo: todo));
                    },
                    child: Text('Add Todo'),
                    style: ElevatedButton.styleFrom(
                      primary: Theme.of(context).primaryColor,
                    ),
                  );
                }),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

_inputField(String label, TextEditingController controller) {
  return Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Text(
        '${label}:',
        style: TextStyle(
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
      ),
      Container(
        height: 50,
        margin: EdgeInsets.only(
          bottom: 10,
        ),
        width: double.infinity,
        child: TextFormField(
          controller: controller,
        ),
      )
    ],
  );
}

CodePudding user response:

If you intend to use a bloc on multiple pages, you must put it above the MaterialApp widget, this is because every page is a child of the MaterialPage, please take a moment to read your error message:

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.

So instead of having

MaterialApp(
  ...
  home: MultiBlocProvider(
    ...
  ),
  ...
);

do this:

MultiBlocProvider(
  ...
  child: MaterialApp(
    ...
  ),
  ...
);
  • Related