1

I'm just starting a new project, and using the Bloc for the first time. I'm getting this error, and I'm sure it's because I'm a newbie to it. This is my code

This is the main.dart code
    void main() {
      runApp(Todo( appRouter: AppRouter(), ));
    }
    
    class Todo extends StatelessWidget {
      final AppRouter appRouter;
      const Todo({Key? key, required this.appRouter}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp( debugShowCheckedModeBanner: false,  home: TodoScreen(),
          onGenerateRoute: appRouter.generateRoute,);
      }
    }

This is the router where I have wrapped the BlocProvider class AppRouter {

  TodoRepository todoRepository = TodoRepository(networkService: NetworkService());

  AppRouter(){
    todoRepository = TodoRepository(networkService: NetworkService());
  }

  Route? generateRoute(RouteSettings routeSettings) {
    switch (routeSettings.name) {
      case "/":
        return MaterialPageRoute(builder: (_) => BlocProvider( create: ( BuildContext context )=> TodosCubit(todoRepository: todoRepository), child: TodoScreen(),));
        break;
      case EDIT_TODO_ROUTE:
        return MaterialPageRoute(builder: (_) => EditTodoScreen());
        break;
      case ADD_TODO_ROUTE:
        return MaterialPageRoute(builder: (_) => AddTodoScreen());
        break;
      default:
        return null;
    }
  }

This is the class that fetches data from the API network

Future<List<dynamic>> fetchTodos() async {
    try{
     final response = await http.get( Uri.parse(base_url + base_port + url) );
     print( response.body );
     jsonDecode(response.body) as List;
    }catch(e){
      print( e );
      return [];
    }
    throw NullThrownError();
  }

The repository that gets the data fetched from the API network

class TodoRepository {

  final NetworkService networkService;
  TodoRepository({required this.networkService});

   Future<List<TodoModel>> fetchTodos()  async {
     final todoRaw = await networkService.fetchTodos();
     return todoRaw.map((e) => TodoModel.fromJson(e)).toList();
  }
}

This is the state that manages data that matches what's expected

@immutable
abstract class TodosState {}

class TodosInitial extends TodosState {}
class TodosLoaded extends TodosState {
  final List<TodoModel> todoModels;
  TodosLoaded({required this.todoModels});
}

This is the cubit that returns the event state to the UI

class TodosCubit extends Cubit<TodosState> {
  final TodoRepository todoRepository;
  TodosCubit({required this.todoRepository}) : super(TodosInitial());

  void fetchTodos() {
    todoRepository.fetchTodos().then((todos) {
      emit(TodosLoaded(todoModels: todos));
    });
  }
}

This is the UI where the data is to be displayed

class TodoScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    BlocProvider.of<TodosCubit>(context).fetchTodos();

    return Scaffold( appBar: AppBar( title: Text('Todo'), actions: [
      InkWell(onTap: ()=> Navigator.pushNamed(context, ADD_TODO_ROUTE),
          child: Padding(padding: const EdgeInsets.all(15.0), child: Icon( Icons.add ),))
    ], ),
      body: Center( child: Text( 'My Todo App' ), ), );
  }
}

When I ran it on Android emulator it returned errors

======== Exception caught by widgets library =======================================================
The following assertion was thrown building TodoScreen(dirty):
        BlocProvider.of() called with a context that does not contain a TodosCubit.

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

        This can happen if the context you used comes from a widget above the BlocProvider.

        The context used was: TodoScreen(dirty)
        
The relevant error-causing widget was: 
  TodoScreen file:///Users/wikiwoo/AndroidStudioProjects/etransfa/lib/main.dart:15:67
When the exception was thrown, this was the stack: 
#0      BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:103:7)
#1      TodoScreen.build (package:etransfa/christdoes/bank/screen/ui/todo_screen.dart:10:18)
#2      StatelessElement.build (package:flutter/src/widgets/framework.dart:4648:28)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
#4      Element.rebuild (package:flutter/src/widgets/framework.dart:4267:5)
...
====================================================================================================

I have checked other SO answers to similar errors but yet I'm unable to see what's wrong and how to fix it.

halfer
  • 19,824
  • 17
  • 99
  • 186
ken4ward
  • 2,246
  • 5
  • 49
  • 89
  • 1
    If you wanna use BlocProvider.of(context).... then you have to do it under the `BlocProvider` widget. So just wrap your MaterialApp's home widget with it and try again, If it couldn't help please provide your full screens – theiskaa Jun 22 '21 at 19:38
  • Thanks. @theiskaa. How do I do that? This is my first time trying this out. Please help with code snippets. – ken4ward Jun 22 '21 at 20:13
  • Okay but I don't know what widget you have as main. Anyway I'll put an answer – theiskaa Jun 22 '21 at 20:15

0 Answers0