I’m using the gsheets package to asynchronously read and write data to a Google spreadsheet. I click a button on an AppBar()
on the home page to add a row to the database. The row is successfully added to the spreadsheet. Here is the code:
// import statements
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool viewNotebooks = false;
bool viewList = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leadingWidth: 650,
leading: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
// code irrelevant to this question, then
TextButton.icon(
icon: const Icon(Icons.note_add_outlined),
label: const Text("New Note"),
onPressed: () async {
await Data.addNote(
title: 'New Note', content: '[content goes here]');
setState(() {});
}),
// more code
],
),
),
body: Row(
children: [
// more code
viewList
? const Expanded(
flex: 1,
child: NotesListView(),
)
: Container(),
// more code
],
),
);
}
}
A ListView.builder()
should then rebuild to include the new row’s data in its items. Here is the relevant code, in a separate .dart file:
import 'package:flutter/material.dart';
import '../providers/sheets_api.dart';
class NotesListView extends StatefulWidget {
const NotesListView({super.key});
@override
State<NotesListView> createState() => _NotesListViewState();
}
class _NotesListViewState extends State<NotesListView> {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Data.getRows(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data![index][1]),
subtitle: Text(snapshot.data![index][2]),
onTap: () async {
var id = snapshot.data![index][0];
// print(await Data.getNoteById(id));
});
},
);
} else {
return const Center(
// render the loading indicator
child: CircularProgressIndicator(),
);
}
},
);
}
}
The widget, however, does not rebuild when the spreadsheet content changes. But when I put the code in the app’s main.dart
file, even in a widget outside _NotesListViewState
, the UI does rebuild as expected.
Widget notesListView() {
return FutureBuilder (
// rest of code
I’m struggling to understand what’s going on. I’ve read about BuildContexts and widget trees, and about keys, and I assume it’s something about the BuildContext for NotesListView
being outside the main app’s widget tree? But I don’t really understand and, if that’s the case, I don’t know how to have NotesListView
be separate (with its own BuildContext) and yet still be seen within the main app’s context. I know I could use something like Provider
to control when widgets rebuild, or just keep the custom notesListView
widget in HomePage, but I’d like to understand what’s going on here.