Flutter - 使用提供者和 Firestore 返回空列表
Flutter - Using provider and Firestore returning empty list
我正在尝试使用来自 Firebase 的数据创建列表。然后我想将此列表传递到我的应用程序的各个部分。当我 运行 我的代码并测试这个元素时,结果显示为一个空列表。这是我的代码。我首先创建一个服务 class:
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): []
有什么建议吗?谢谢
我会尝试这种方法:
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>>
该列表内部的内容已转换为 List<String>
,所以现在您有一个 List<List<String>>
,但您想要一个 List<String>
,而不是嵌套列表,因此您使用运算符 expand
可用于展平列表,它 'expands' 里面的内容所以结果将是 List<String>
.
作为最后的说明,如果您的文档可以保存不同于 String 的数据,也许您可以尝试使用 whereType<Map>()
而不是 cast()
来仅保留 String
的值
我正在尝试使用来自 Firebase 的数据创建列表。然后我想将此列表传递到我的应用程序的各个部分。当我 运行 我的代码并测试这个元素时,结果显示为一个空列表。这是我的代码。我首先创建一个服务 class:
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): []
有什么建议吗?谢谢
我会尝试这种方法:
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>>
该列表内部的内容已转换为 List<String>
,所以现在您有一个 List<List<String>>
,但您想要一个 List<String>
,而不是嵌套列表,因此您使用运算符 expand
可用于展平列表,它 'expands' 里面的内容所以结果将是 List<String>
.
作为最后的说明,如果您的文档可以保存不同于 String 的数据,也许您可以尝试使用 whereType<Map>()
而不是 cast()
来仅保留 String