I'm starting with flutter as I want to port my swift app to Flutter, but I'm getting stuck understanding the pattern Bloc/Repository/Firebase as I'm following the tutorial https://bloclibrary.dev/#/flutterfirestoretodostutorial dough I use the real time database, not Firestore. My swift app is basically a map where you can add Alerts at your actual coordinates. The Alert get sent to Firebase and the firebase observer on the map updates the map showing the just added alert. The above tutorial should help me porting my app. I'm just not sure I do understand the logic behind the code. My concerns are 2:
First. There is an Entity
layer between the model object and the firebase object. It is explained that this will facilitate having different Data providers, but I don't really see it facilitating anything. In the Model
class there is a toEntity()
and a fromEntity()
conversion method, and in the Entity
class there is a fromSnapshot()
and a toDocument()
conversion method. I don't see what's the point here. Is it really necessary? What's wrong with doing the conversion directly in the Model
class , having different methods for each Data provider?
Second. Inside the TodoBloc
I can't follow the logic.
The first event that is sent to the bloc at AppStart
is LoadTodos
.
BlocProvider<TodosBloc>(
create: (context) {
return TodosBloc(
todosRepository: FirebaseTodosRepository(),
)..add(LoadTodos());
In the mapEventToState()
method of TodoBloc
that event gets mapped to this Stream:
Stream<TodosState> _mapLoadTodosToState() async* {
_todosSubscription?.cancel();
_todosSubscription = _todosRepository.todos().listen(
(todos) => add(TodosUpdated(todos)),
);
}
So far so good. As I understand this subscribes to the todos()
Stream ()
@override
Stream<List<Todo>> todos() {
return todoCollection.snapshots().map((snapshot) {
return snapshot.documents
.map((doc) => Todo.fromEntity(TodoEntity.fromSnapshot(doc)))
.toList();
});
}
and this should be the equivalent of the firebase observer in my swift app. It this part inside the listen
closure I'm not sure to understand: (todos) => add(TodosUpdated(todos))
.
This sends to itself (TodoBloc) a TodosUpdated
event on which the bloc will map this Stream:
Stream<TodosState> _mapTodosUpdatedToState(TodosUpdated event) async* {
yield TodosLoaded(event.todos);
}
which is this:
class TodosLoaded extends TodosState {
final List<Todo> todos;
const TodosLoaded([this.todos = const []]);
@override
List<Object> get props => [todos];
@override
String toString() => 'TodosLoaded { todos: $todos }';
}
Is this the actual list of Firebase objects? Does the todos()
Stream return the entire node every time a new object is added in Firebase?
In my swift app the observer returns only the .childAdded
after the first download of the node.
Should I use the firebase_database
package that has a FirebaseList
class(https://pub.dev/documentation/firebase_database/latest/ui_firebase_list/FirebaseList-class.html) that will just return a List on any change on the node as my observers do in my swift app?
Sorry for this very long and messy question, but I'm quite lost here starting with bloc pattern.
Thank you very much for your time and help.