Flutter:如何从Firestore获取数据生成可点击变色Chips?
问题描述
我已经实现了从本地列表生成Chips的功能,点击Chips时颜色会变为蓝色。现在希望替换本地的wordList,改为从Firestore数据库中获取数据,将集合中的"WordName"字段内容显示在Chips上。现有代码如下:
class uitry extends StatefulWidget { const uitry({Key? key}) : super(key: key); @override State<uitry> createState() => _uitryState(); } class _uitryState extends State<uitry> { List<String> wordList = [ 'Shopping', 'Brunch', 'Music', 'Road Trips', 'Tea', 'Trivia', 'Comedy', 'Clubbing', 'Drinking', 'Wine', ]; List<String> selectedWord = []; List<String>? deSelectedWord = []; @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; return Scaffold( body: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage(Config.app_background4), fit: BoxFit.fill), ), child: SafeArea( child: Center( child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.only(top: 14, right: 0), child: Column( children: [ SizedBox( width: width * 0.94, height: height * 0.30, child: Column( children: <Widget>[ const SizedBox(height: 16), Wrap( children: wordList.map( (word) { bool isSelected = false; if (selectedWord!.contains(word)) { isSelected = true; } return GestureDetector( onTap: () { if (!selectedWord!.contains(word)) { if (selectedWord!.length < 50) { selectedWord!.add(word); deSelectedWord!.removeWhere( (element) => element == word); setState(() {}); print(selectedWord); } } else { selectedWord!.removeWhere( (element) => element == word); deSelectedWord!.add(word); setState(() { // selectedHobby.remove(hobby); }); print(selectedWord); print(deSelectedWord); } }, child: Container( margin: const EdgeInsets.symmetric( horizontal: 5, vertical: 4), child: Container( padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 12), decoration: BoxDecoration( color: isSelected ? HexColor('#0000FF') : HexColor('#D9D9D9'), borderRadius: BorderRadius.circular(18), border: Border.all( color: isSelected ? HexColor('#0000FF') : HexColor('#D9D9D9'), width: 2)), child: Text( word, style: TextStyle( color: isSelected ? Colors.black : Colors.black, fontSize: 14, fontWeight: FontWeight.w600), ), ), ), ); }, ).toList(), ), ], ), ), ], ), ), ], ))), ), ); } }
解决方案
要实现从Firestore获取数据生成Chips,按以下步骤修改代码:
1. 添加Firestore依赖
在pubspec.yaml中添加Firebase相关依赖(如果未添加):
dependencies: flutter: sdk: flutter cloud_firestore: ^4.15.0 # 使用最新版本 firebase_core: ^2.24.2 # 初始化Firebase必需
执行flutter pub get完成依赖安装。
2. 修改状态类,添加Firestore数据获取逻辑
更新_uitryState类,添加异步获取数据的方法,并处理加载状态:
class _uitryState extends State<uitry> { List<String> wordList = []; List<String> selectedWord = []; List<String> deSelectedWord = []; // 移除可空标记,直接初始化空列表 bool isLoading = true; // 新增加载状态标识 @override void initState() { super.initState(); fetchWordsFromFirestore(); // 页面初始化时获取数据 } // 从Firestore获取WordName字段的异步方法 Future<void> fetchWordsFromFirestore() async { try { // 替换为你的Firestore集合名称,示例为"words" QuerySnapshot snapshot = await FirebaseFirestore.instance.collection("words").get(); // 遍历文档,提取WordName字段 List<String> fetchedWords = snapshot.docs.map((doc) { return doc["WordName"] as String; }).toList(); setState(() { wordList = fetchedWords; isLoading = false; // 数据加载完成,更新状态 }); } catch (e) { print("Firestore数据获取失败: $e"); setState(() { isLoading = false; }); } } // 原build方法修改见下一步 }
3. 调整UI,处理加载状态
在build方法中,根据isLoading状态显示加载提示或Chips列表:
@override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; return Scaffold( body: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage(Config.app_background4), fit: BoxFit.fill), ), child: SafeArea( child: Center( child: Column( children: <Widget>[ Padding( padding: const EdgeInsets.only(top: 14, right: 0), child: Column( children: [ SizedBox( width: width * 0.94, height: height * 0.30, child: Column( children: <Widget>[ const SizedBox(height: 16), // 根据加载状态显示不同内容 isLoading ? const CircularProgressIndicator() // 加载中显示进度圈 : Wrap( children: wordList.map( (word) { bool isSelected = selectedWord.contains(word); // 简化选中判断 return GestureDetector( onTap: () { setState(() { if (!isSelected) { if (selectedWord.length < 50) { selectedWord.add(word); deSelectedWord.remove(word); } } else { selectedWord.remove(word); deSelectedWord.add(word); } print(selectedWord); print(deSelectedWord); }); }, child: Container( margin: const EdgeInsets.symmetric( horizontal: 5, vertical: 4), child: Container( padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 12), decoration: BoxDecoration( color: isSelected ? HexColor('#0000FF') : HexColor('#D9D9D9'), borderRadius: BorderRadius.circular(18), border: Border.all( color: isSelected ? HexColor('#0000FF') : HexColor('#D9D9D9'), width: 2)), child: Text( word, style: TextStyle( color: Colors.black, fontSize: 14, fontWeight: FontWeight.w600), ), ), ), ); }, ).toList(), ), ], ), ), ], ), ), ], ))), ), ); }
4. 额外优化点
- 移除了
selectedWord和deSelectedWord的可空标记,避免不必要的空安全判断 - 简化了
isSelected的判断逻辑,直接通过selectedWord.contains(word)获取状态 - 合并了
setState调用,减少状态更新次数
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

