FutureBuilder
This commit is contained in:
@@ -16,59 +16,44 @@ class GroceryList extends StatefulWidget {
|
||||
|
||||
class _GroceryListState extends State<GroceryList> {
|
||||
List<GroceryItem> _groceryItems = [];
|
||||
var _isLoading = true;
|
||||
late Future<List<GroceryItem>> _loadedItems;
|
||||
String? _error;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadItems();
|
||||
_loadedItems = _loadItems();
|
||||
}
|
||||
|
||||
void _loadItems() async {
|
||||
Future<List<GroceryItem>> _loadItems() async {
|
||||
final url = Uri.https(
|
||||
'flutter-prep-dccfe-default-rtdb.firebaseio.com', 'shopping-list.json');
|
||||
|
||||
try {
|
||||
final response = await http.get(url);
|
||||
final response = await http.get(url);
|
||||
|
||||
if (response.statusCode >= 400) {
|
||||
setState(() {
|
||||
_error = 'Failed to fetch data. Please try again later.';
|
||||
});
|
||||
}
|
||||
|
||||
if (response.body == 'null') {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, dynamic> listData = json.decode(response.body);
|
||||
final List<GroceryItem> loadedItems = [];
|
||||
for (final item in listData.entries) {
|
||||
final category = categories.entries
|
||||
.firstWhere(
|
||||
(catItem) => catItem.value.title == item.value['category'])
|
||||
.value;
|
||||
loadedItems.add(GroceryItem(
|
||||
id: item.key,
|
||||
name: item.value['name'],
|
||||
quantity: item.value['quantity'],
|
||||
category: category,
|
||||
));
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_groceryItems = loadedItems;
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (error) {
|
||||
setState(() {
|
||||
_error = 'Something went wrong. Please try again later.';
|
||||
});
|
||||
if (response.statusCode >= 400) {
|
||||
throw Exception('Failed to fetch grocery items. Please try again later.');
|
||||
}
|
||||
|
||||
if (response.body == 'null') {
|
||||
return [];
|
||||
}
|
||||
|
||||
final Map<String, dynamic> listData = json.decode(response.body);
|
||||
final List<GroceryItem> loadedItems = [];
|
||||
for (final item in listData.entries) {
|
||||
final category = categories.entries
|
||||
.firstWhere(
|
||||
(catItem) => catItem.value.title == item.value['category'])
|
||||
.value;
|
||||
loadedItems.add(GroceryItem(
|
||||
id: item.key,
|
||||
name: item.value['name'],
|
||||
quantity: item.value['quantity'],
|
||||
category: category,
|
||||
));
|
||||
}
|
||||
return loadedItems;
|
||||
}
|
||||
|
||||
void _addItem() async {
|
||||
@@ -107,39 +92,6 @@ class _GroceryListState extends State<GroceryList> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget content = const Center(child: Text('No items added yet.'));
|
||||
|
||||
if (_isLoading) {
|
||||
content = const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (_groceryItems.isNotEmpty) {
|
||||
content = ListView.builder(
|
||||
itemCount: _groceryItems.length,
|
||||
itemBuilder: (ctx, index) => Dismissible(
|
||||
onDismissed: (direction) {
|
||||
_removeItem(_groceryItems[index]);
|
||||
},
|
||||
key: ValueKey(_groceryItems[index].id),
|
||||
child: ListTile(
|
||||
title: Text(_groceryItems[index].name),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: _groceryItems[index].category.color,
|
||||
),
|
||||
trailing: Text(
|
||||
_groceryItems[index].quantity.toString(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (_error != null) {
|
||||
content = Center(child: Text(_error!));
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Your Groceries'),
|
||||
@@ -150,7 +102,43 @@ class _GroceryListState extends State<GroceryList> {
|
||||
),
|
||||
],
|
||||
),
|
||||
body: content,
|
||||
body: FutureBuilder(
|
||||
future: _loadedItems,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (snapshot.hasError) {
|
||||
return Center(child: Text(snapshot.error.toString()));
|
||||
}
|
||||
|
||||
if (snapshot.data!.isEmpty) {
|
||||
return const Center(child: Text('No items added yet.'));
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: snapshot.data!.length,
|
||||
itemBuilder: (ctx, index) => Dismissible(
|
||||
onDismissed: (direction) {
|
||||
_removeItem(snapshot.data![index]);
|
||||
},
|
||||
key: ValueKey(snapshot.data![index].id),
|
||||
child: ListTile(
|
||||
title: Text(snapshot.data![index].name),
|
||||
leading: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: snapshot.data![index].category.color,
|
||||
),
|
||||
trailing: Text(
|
||||
snapshot.data![index].quantity.toString(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user