I'm trying to get my head around how I should manage reading data from a database in Flutter (or any API/backend).
Without a database and just using state that's local to the widget I'd expect to write something similar to the following. I am printing out a list of strings in a ListView
and adding a new one when a FloatingActionButton
is pressed.
class _ListScreenState extends State<ListScreen> {
var _myStrings = ["string1", "string2"];
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: _myStrings.length,
itemBuilder: (BuildContext context, int index) {
return Text(_myStrings[index]);
}
),
floatingActionButton: FloatingActionButton(
onPressed: () => {
setState(() {
_myStrings.add("another string");
});
},
child: const Icon(Icons.add),
),
);
}
}
However, when reading from a database, I've extracted the database logic behind a repository class and so I'm using a FutureBuilder.
class _ListScreenState extends State<ListScreen> {
final _repo = FooRepository();
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _repo.getAll(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data == null) {
return const Center(child: Text("Loading..."));
}
return ListView<String, String>(
elements: snapshot.data,
itemBuilder: (context, element) {
return Text(element);
}
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => {
_repo.add("newstring");
},
child: const Icon(Icons.add),
),
);
}
}
This seems to go against the idea of the flutter widget being reactive to changes in its local state. Am I doing something wrong here? I don't know whether calling setState()
will cause the FutureBuilder
to redraw but it also seems wasteful to re-get all the records from the database when one is added. Should/can I hold a copy of the strings locally to the widget and add to both the database but also the local list?