I am new to flutter and especially provider pattern. I went through the documentation, examples and some tutorials for the provider pattern statemanagement and i am trying to implement it in one of my projects. I am developing a personal expenses manager app. The problem is that all the documentation, examples and tutorials assume the model provider has all the required data available in memory, that is, all the mock data is already there in a list. It is fairly easy to understand the addition/deletion of data and the change notification. But in a real app, the data needs to be loaded either from the local database or from the Internet. That is when things gets confusing and messy. Here is my model:
class Expense {
int id;
String name;
DateTime date;
double amount;
PaymentType paymentType; //This is an enum (card, cash etc.)
ExpenseCategory category; //Categories like fuel, groceries etc.
Expense({@required this.name, @required this.date, @required this.amount, @required this.paymentType, @required this.category});
}
class ExpenseCategory {
int id;
String name;
ExpenseCategory({@required this.name});
}
Data manipulation class:
class ExpenseRepository {
static Future<List<Expense>> getAllExpenses({@required int month}) async {
return await mockService.getAllExpensesData(month: month);
}
static Future<List<Expense>> getRecentExpenses() async {
return await mockService.getRecentExpensesData();
}
static Future<List<CategorywiseAmount>> getCategorywiseExpensesList({@required int month}) async {
return await mockService.getCategorywiseExpensesListData(month: month);
}
}
The data is, for the time being, loaded from a mock service which will be replaced by the local database. Nevertheless, it simulates the async/await pattern.
Keeping the above code in view, i have the following questions:
Do i have to convert the "Expense" model into a provider ("Expense" and "Expenses" provider) or do i have to create a separate class which will act as a provider? In the docs and tutorials, i have seen that the models have been converted to providers but is that the right thing to do? I may be wrong but i think the separation of concerns will be violated. As far as i have read, a model should not do anything else other than being a model.
How does the expense provider actually load data from the database (or from the mock database in my case)? If i follow the tutorials, i have to have a provider like this:
class ExpensesProvider with ChangeNotifier {
List<Expense> _expensesList;
List<Expense> get recentExpenses {
return _expensesList;
}
}
But how will the provider load data from mock database into the _expensesList property because the mock method getRecentExpenses() returns a future (and the real one will too) and that can't be used in the getter. Or do i have to return a future from the getter itself too?
- If a new expense is added, the list of recent expenses should update automatically. Let's assume for the time being this provider is somehow hooked to the database. I have the following doubts: a) Does the provider watch for the changes in the database or does it watch for changes in the in-memory model/list and trigger the rebuilds automatically? b) Or maybe it doesn't watch any of above and we need to manually trigger it with notifyListeners? The confusion comes from the comments
// Consumer looks for an ancestor Provider widget
// and retrieves its model (Counter, in this case).
// Then it uses that model to build widgets, and will trigger
// rebuilds if the model is updated.
These comments are from the flutter samples app https://github.com/flutter/samples/blob/master/provider_counter/lib/main.dart
- Am i even using the right tools? I mean maybe there is something else which can be used instead of provider (but with similar or more feature) for use with local/database to make the process simpler.