I can't figure out why the TodoList doesn't load immediately when I enter the app. Instead of a list, I get a TodoEmptyState status, even if I already have saved items in the DB, it's still an empty list at first. But after that, when I add a new element and update it, then it will load. But I want the list to be immediately loaded (if there are saved items) when entering the application without clicking on the buttons. Please tell me how to do it?
home_screen
Widget build(BuildContext context) {
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Todos'),
),
body: SingleChildScrollView(
child: Column(
children: [
TodoList(),
],
),
),
todo_list
class TodoList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
if (state is TodoEmptyState) {
return const Center(
child: Text(
'No Todo',
style: TextStyle(fontSize: 20.0),
),
);
}
if (state is TodoLoadingState) {
return const Center(child: CircularProgressIndicator());
}
if (state is TodoLoadedState) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.loadedUser.length,
itemBuilder: (context, index) =>
// return _buildListTile(state.loadedUser[index]);
ListTile(
title: Column(children: [
Text('${state.loadedUser[index].description}'),
Text('${state.loadedUser[index].id}'),
]),
trailing: IconButton(
onPressed: () {
todoBloc.add(DeleteTodos(id: state.loadedUser[index].id));
todoBloc.add(LoadTodos());
},
icon: const Icon(Icons.delete),
),
));
}
return const SizedBox.shrink();
});
}
}
todo_bloc
class TodoBloc extends Bloc<TodoEvent, TodoState> {
final TodoRepository todoRepository;
TodoBloc(this.todoRepository) : super(TodoEmptyState()) {
on<LoadTodos>((event, emit) async {
emit(TodoLoadingState());
try {
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
} catch (_) {
emit(TodoErrorState());
}
});
Here is the screen when entering the application, but I already have data in the DB, but they were not immediately displayed. Why?
CodePudding user response:
Right now the only place you add any event to your bloc is inside onPressed of the IconButton which is why your bloc state remains in its initial state TodoEmptyState and doesn't change until the IconButton is pressed. You can convert your TodoList to a StatefulWidget and add the LoadTodos event to the bloc in initState:
class TodoList extends StatefulWidget {
@override
State<TodoList> createState() => _TodoListState();
}
class _TodoListState extends State<TodoList> {
@override
void initState() {
super.initState();
todoBloc.add(LoadTodos());
}
@override
void dispose() {
todoBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
if (state is TodoEmptyState) {
return const Center(
child: Text(
'No Todo',
style: TextStyle(fontSize: 20.0),
),
);
}
if (state is TodoLoadingState) {
return const Center(child: CircularProgressIndicator());
}
if (state is TodoLoadedState) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.loadedUser.length,
itemBuilder: (context, index) =>
// return _buildListTile(state.loadedUser[index]);
ListTile(
title: Column(children: [
Text('${state.loadedUser[index].description}'),
Text('${state.loadedUser[index].id}'),
]),
trailing: IconButton(
onPressed: () {
todoBloc.add(DeleteTodos(id: state.loadedUser[index].id));
todoBloc.add(LoadTodos());
},
icon: const Icon(Icons.delete),
),
));
}
return const SizedBox.shrink();
});
}
}

