I have a simple app with list of Task
s. Each Task
is time bound.
@freezed
class Task with _$Task {
const factory Task({
@Default('') String title,
required DateTime start,
required DateTime end,
}) = _Task;
}
Then I display the tasks using provider, e.g.:
class TasksController extends StateNotifier<List<Task>> {
TasksController()
: super(const []) {
init();
}
Future<void> init() async {
state = await GetTasksFromSomeRepo();
}
}
I would like to show indicator that task is happening now, e.g.:
There exists a simple solution, where I do rebuild entire list of Task
‘s widgets every 1 second, using:
Timer.periodic(Duration(seconds: 1), (Timer t) {
setState(() {
// this calls build method
});
});
and in build
method itself I check if DateTime.now()
is within each Task
"start/end" bounds.
This however seems like an inefficient approach.
Question:
- How to do it with in more efficient way, ideally with help of a Riverpod?
3
Answers
Since you do not comunicate with any API the only way to check for something in progress is, as you mention in the question, with a timer.
What you can do however is, instead of calling
setState
, change something intask
(you could would create a new variablestate
) by accessing theTasksController
.If implemented correctly, that should trigger a state change that rebuilds only the right widgets, instead of the whole widget tree.
task_resolver.dart :
on ui.dart:
A more efficient solution using
setState
, here theTaskContainer
widget is rebuilt at most twice.An example page for testing it.
EDIT: Implementation with riverpod
You can achieve the same by using a family of providers that take a task as a parameter. Your
Task
class should be immutable and override== operator
andhashcode
.Provider:
Convert
TaskContainer
toConsumerWidget
: