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&lt;String, dynamic&gt;,所以您有一个List&lt;Map&lt;String, dynamic&gt;&gt;,并且该列表中的内容被转换为@ 987654328@,所以现在你有一个List&lt;List&lt;String&gt;&gt;,但是你想要一个List&lt;String&gt;,而不是一个嵌套列表,所以你使用运算符expand,它可以用来展平一个列表,它“扩展”里面的东西所以结果将是List&lt;String&gt;

最后一点,如果您的文档可以保存不同于 String 的数据,也许您可​​以尝试使用 whereType&lt;Map&gt;() 而不是 cast() 来仅保留 String 的值

【讨论】:

感谢您提供如此全面的答案。绝对帮助我更好地理解了这个过程!

以上是关于Flutter - 使用提供者和 Firestore 返回空列表的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:当应用程序在后台时使用路径提供程序

Flutter CRUD 模型与提供者

Flutter 中提供者的单元测试

你如何在 Flutter 中创建服务/提供者?

Flutter - 使用提供程序时 whenComplete() 无法按预期工作

Flutter - 使用 StreamBuilder 提供对谷歌地图的实时更新