I am learning Flutter and the BLoC pattern from the Bloc library. I think I just about understand the Todo example, but I'm trying to build upon it to do something just a tad more complex, and I'm hitting a wall.
So, my issue is this. Let's consider the Todo example https://bloclibrary.dev/#/fluttertodostutorial
Contrary to what the (probably outdated) GIF animation on that page is representing, when you click on a Todo, you don't get to a "Todo details" page from which you can then go to an "Edit todo" page. You get directly to the edit page in a single step:
Todo list -> Edit todo
What I'm trying to do is to have the "two-step" flow that can be seen in the animation:
Todo list -> Todo details -> Edit todo
So, in the code, the actual "one-step" flow works like that: when you click on a todo, you are taken to the EditTodoPage, which has its own EditTodoBloc. This Bloc is initialized with the todo you clicked on, but in a "plain" way, just by passing the model of the todo (initialTodo
).
// in EditTodoPage
static Route<void> route({Todo? initialTodo}) {
return MaterialPageRoute(
fullscreenDialog: true,
builder: (context) => BlocProvider(
create: (context) => EditTodoBloc(
todosRepository: context.read<TodosRepository>(),
initialTodo: initialTodo,
),
child: const EditTodoPage(),
),
);
}
This means that EditTodoBloc is not "reactive" to changes to the todo. This works because the EditTodoPage is the only place where the todo gets updated, so it can just have its own state. Then when the todo is saved, it is saved in the repository, and you are taken back to the list, which is reactive via the repository and stream and everything.
But how would you adapt that to work with the "two-step" flow? The naive solution may be to use the same Bloc for both pages, but for the sake of argument (and because it seems to be a good practice to have one Bloc per page), let's say we want a TodoDetailsBloc for the details page and an EditTodoBloc for the edit page. The edits made on the edit page must now be reflected on the details page so we can't just pass the todo model to the blocs naively.
Should the two Blocs listen to a new stream from the repository? A stream that would only return that particular Todo? I'm not sure how and when that stream would get created and what its lifecycle would be; and I'm not sure it's the concern of the repository to do that. Or maybe should the two Blocs communicate to each other directly via events? But to me this seems to disrupt the nice top-down repository-bloc-widget data flow.
So, how would that look like in practice?
Or alternatively, if you have a good example of a (slightly) more complex app that I could study, I would gladly take that too.
Thanks :)
These kind of opinionated questions are part of design choices and are heavily dependent on what you are trying to achieve. The following is just my opinion:
I hope I could help you with that. Please keep in mind that these answers are more based on opinions. There are no right and wrong answers.