my UI consists of a table of objects Apples.
Every cell in the table:
- has an ADD button, if the apple is NOT present for that cell
- it shows the apple and has a DELETE button, if the apple is present
The main page of my application is calling the following widget to LOAD the LIST of apples from an API. And also the ADD and DELETE functions communicate with the same API for adding and deleting the apple.
class ApplesLoader extends StatefulWidget {
@override
_ApplesLoaderState createState() => _ApplesLoaderState();
}
class _ApplesLoaderState extends State<ApplesLoader> {
@override
void initState() {
super.initState();
BlocProvider.of<ApplesCubit>(context).getAll();
}
@override
Widget build(BuildContext context) {
return BlocConsumer<ApplesCubit, ApplesState>(
listener: ...,
builder: (ctx, state) {
if (!(state is ApplesLoaded)) {
return circularProgressIndicator;
}
return ApplesViewer(state.Apples);
},
);
}
}
So after that ApplesViewerhas the list of apples and can correctly display the grid.
But now I have two problems:
When I press the ADD button or the DELETE button, all the application is rebuilt, while I could actually just re-paint the cell. But I don't know how to avoid this, because I also need to communicate to the application that the list of apples is actually changed. I don't want to rebuild the entire UI because it seems inefficient since what is actually changing on my page is only the selected cell.
When I press the ADD button or the DELETE button, I would like to show a circular progress indicator that replaces the button (while waiting for the API to actually creating/deleting the apple). But when the list changes, all the application is rebuilt instead. So, I am not sure how to achieve this desired behavior.
Could you help me in solving those two issues?
Or advise me for a change of infrastructure in case I am making some mistake in dealing with this?
If needed, this is the code for ApplesCubit
class ApplesCubit extends Cubit<ApplesState> {
final ApplesRepository _repository;
ApplesCubit(this._repository) : super(ApplesLoading());
Future<void> getAll() async {
try {
final apples = await _repository.getAll();
emit(ApplesLoaded(List<Apple>.from(apples)));
} on DataError catch (e) {
emit(ApplesError(e));
}
}
Future<void> create(List<Apple> apples, Apple appleToAdd) async {
try {
final newApple = await _repository.create(appleToAdd);
final updatedApples = List<Apple>.from(apples)..add(newApple);
emit(ApplesLoaded(updatedApples));
} on DataError catch (e) {
emit(ApplesError(e));
}
}
Future<void> delete(List<Apple> Appless, Apple appleToDelete) async {
try {
await _repository.deleteApples(appleToDelete);
final updatedApples = List<Apple>.from(Appless)..remove(appleToDelete);
emit(ApplesLoaded(updatedApples));
} on DataError catch (e) {
emit(ApplesError(e));
}
}
}