main.dart
void main() => runApp(DemoApp()); class DemoApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text("Favorite languages"), ), body: const FavoriteList(), ), ); } }
favorite_list_widget.dart
class FavoriteList extends StatelessWidget { static Stream<QuerySnapshot> getStream() => FirebaseFirestore .instance .collection("languages") .orderBy("likes", descending: true) // 1 .snapshots(); // 2 const FavoriteList(); @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: getStream(), builder: (context, languages) { if (languages.hasError) { return const ErrorWidget(); } if (languages.hasData) { final data = languages.data; if (data != null) { return ListView.builder( itemExtent: 80.0, itemCount: data.docs.length, itemBuilder: (context, index) => LanguageItem(data.docs[index]), ); } else { return const ErrorWidget(); } } return const Center( child: CircularProgressIndicator() ); }, ); } }
language_item.dart
class LanguageItem extends StatelessWidget { final String name; final int likes; final String asset; final QueryDocumentSnapshot _snapshot; LanguageItem(this._snapshot) : asset = _snapshot.get("image") as String, likes = _snapshot.get("likes") as int, name = _snapshot.get("name") as String; @override Widget build(BuildContext context) { return ListTile( leading: FlutterLogo( size: 45, ), title: Text(name), subtitle: Text("Total likes: $likes"), trailing: IconButton( icon: const Icon(Icons.thumb_up), iconSize: 20, color: Colors.lightGreen, onPressed: _updateVote, ), ); } void _updateVote() { FirebaseFirestore.instance.runTransaction((transaction) async { final secureSnapshot = await transaction.get(_snapshot.reference); final currentLikes = secureSnapshot.get("likes") as int; transaction.update(secureSnapshot.reference, { "likes": currentLikes + 1 }); }); } }
error_widget.dart
class ErrorWidget extends StatelessWidget { const ErrorWidget(); @override Widget build(BuildContext context) { return const Center( child: Icon(Icons.error_outline, color: Colors.redAccent, size: 20, ), ); } }
This website and the book are not official Google products. No affiliations are involved. Built with Java 14 and Vert.X
"Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC"