Flutter - 使用提供者和 Firestore 返回空列表
Posted
技术标签:
【中文标题】Flutter - 使用提供者和 Firestore 返回空列表【英文标题】:Flutter - Using provider and Firestore returning empty list 【发布时间】:2021-02-20 11:25:23 【问题描述】:我正在尝试使用 Firebase 中的数据创建一个列表。然后我想将此列表传递给我的应用程序的各个部分。当我运行我的代码并测试这个元素时,结果显示为一个空列表。这是我的代码。我首先创建一个服务类:
class OccasionServices
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<String>> getAllOccasions(currentUser) async => _firestore
.collection('collections')
.doc(currentUser)
.collection('occasions')
.get()
.then((snap)
List<String> allOccasions = [];
snap.docs.forEach((snapshot) => snapshot
.data()
.entries
.map((mapEntry) => allOccasions.add((mapEntry.value))));
return allOccasions;
);
然后我使用 ChangeNotifier 创建我的 Provider:
class CollectionProvider with ChangeNotifier
User result = FirebaseAuth.instance.currentUser;
List<String> _allOccasions = [];
OccasionServices _occasionServices = OccasionServices();
CollectionProvider()
_getAllOccasions();
//getter
List<String> get allOccasions => _allOccasions;
void _getAllOccasions() async
_allOccasions = await _occasionServices.getAllOccasions(result.uid);
notifyListeners();
然后将提供程序添加到我的 main.dart 文件中:
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: CollectionProvider()
),
],),
child: MaterialApp(
title: 'My App',
home: SignInPage(),
),
);
但是当我在我的应用程序的另一部分使用这个列表时,我只能访问一个空列表:
Widget build(BuildContext context)
final collectionProvider = Provider.of<CollectionProvider>(context);
final collections = collectionProvider.allOccasions;
print(collections);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurpleAccent,
title: Text('Viewer'),
),
body: Container(
child: Text('body'),
),
);
结果:
I/flutter ( 4160): []
有什么建议吗?谢谢
【问题讨论】:
您好,您能否在notifyListeners();
之前打印_occasionServices.getAllOccasions 的返回值。例如通过添加 print("_getAllOccasions: $_allOccasions");
嗨,dumazy,这也返回一个空列表。这一定意味着我在 OccasionServices 中的 getAllOccasions 函数存在问题。我会在那里开始调查。
更新:我的 firestore 查询返回了文档快照。我认为问题可能出在函数的“地图”部分。
您是否能够修复函数的“地图”部分?如果没有,我可以给你一个解决方案。
您好 Chichebe,我还无法修复它。如果您能帮助我,将不胜感激。
【参考方案1】:
我会尝试这种方法:
class OccasionServices
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<String>> getAllOccasions(currentUser) async => _firestore
.collection('collections')
.doc(currentUser)
.collection('occasions')
.get()
.then((snap) =>
snap.docs
.map((doc) => doc.data().values.cast<String>())
.expand((e) => e).toList()
)
一步一步,每件事是做什么的:
/// this will convert each doc in the docs List and return a new List of what is inside,
/// it will get all the values of the Map<String dynamic> returned by data() as a List<dynamic>
/// then you will cast them to String with .cast<String> (you have to be sure each value can be casted to String or it will throw)
.map((doc) => doc.data().values.cast<String>())
在此之前,您有一个QuerySnapshot
,其中有一个QueryDocumentSnapshot
列表,每个QueryDocumentSnapshot
都有一个Map<String, dynamic>
,所以您有一个List<Map<String, dynamic>>
,并且该列表中的内容被转换为@ 987654328@,所以现在你有一个List<List<String>>
,但是你想要一个List<String>
,而不是一个嵌套列表,所以你使用运算符expand
,它可以用来展平一个列表,它“扩展”里面的东西所以结果将是List<String>
。
最后一点,如果您的文档可以保存不同于 String 的数据,也许您可以尝试使用 whereType<Map>()
而不是 cast()
来仅保留 String 的值
【讨论】:
感谢您提供如此全面的答案。绝对帮助我更好地理解了这个过程!以上是关于Flutter - 使用提供者和 Firestore 返回空列表的主要内容,如果未能解决你的问题,请参考以下文章