【问题标题】:How do I return a subcollection using StreamProvider? [Flutter, Firebase]如何使用 StreamProvider 返回子集合? [颤振,火力基地]
【发布时间】:2021-07-16 14:05:33
【问题描述】:

我遵循了 TheNetNin​​ja 的 Flutter 和 Firebase 教程,但现在我正在尝试显示来自子集合的信息。

class Menu extends StatefulWidget {
  @override
  _MenuState createState() => _MenuState();
}

class _MenuState extends State<Menu> {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<List<Food>>.value(
      initialData: [],
      value: DatabaseService().food,
      child: Scaffold(
        body: Container(
          padding: EdgeInsets.symmetric(horizontal: 10),
          width: double.infinity,
          color: Colors.grey,
          child: FoodList(),
        ),
      ),
    );
  }

^menu.dart

class FoodList extends StatefulWidget {
  @override
  _FoodListState createState() => _FoodListState();
}

class _FoodListState extends State<FoodList> {
  @override
  Widget build(BuildContext context) {
    final food = Provider.of<List<Food>>(context);
    return ListView.builder(
      itemCount: food.length,
      itemBuilder: (context, index) {
        return FoodTile(food: food[index]);
      },
    );
  }
}

^food_list.dart

class FoodTile extends StatelessWidget {
  final Food food;
  FoodTile({this.food});

  @override
  Widget build(BuildContext context) {
    return foodInfoCard(context, Icons.person_outline, 'Name', food.name);
  }

  Card foodInfoCard(
      BuildContext context, IconData icon, String title, String subtitle) {
    return Card(
      margin: EdgeInsets.fromLTRB(20, 6, 20, 0),
      child: ListTile(
        leading: Icon(icon),
        title: Text(title),
        subtitle: Text(subtitle),
      ),
    );
  }
}

^food_tile.dart

class DatabaseService {
  final String uid;
  DatabaseService({this.uid});

  final CollectionReference restaurantCollection =
      FirebaseFirestore.instance.collection('restaurant');
  List<Food> _foodListFromSS(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return Food(
        name: doc.data()['name'] ?? '',
        description: doc.data()['description'] ?? '',
        oriPrice: doc.data()['oriPrice'] ?? 0.0,
        salePrice: doc.data()['salePrice'] ?? 0.0,
        pax: doc.data()['pax'] ?? 0,
      );
    }).toList();
  }

  Stream<List<Food>> get food {
    return restaurantCollection
        .doc(uid)
        .collection('food')
        .snapshots()
        .map(_foodListFromSS);
  }
}

^database.dart

我一直在寻找解决方案,但其中大多数是流构建器而不是流提供者。我已经使用 streamproviders 完成了大部分工作,所以我想知道如何更改它。谁能帮我? :'(

【问题讨论】:

    标签: android firebase flutter


    【解决方案1】:

    您需要将uid 提供给Menu 小部件中的DatabaseService 构造函数。

    这个:

          value: DatabaseService().food,
    

    应该改为:

          value: DatabaseService(uid).food,
    

    此外,由于uidDatabaseService 的必需参数,您可以将其标记为@required,以便分析器显示传递该参数的提示。见下文:

    class DatabaseService {
      final String uid;
    
      DatabaseService({@required this.uid}); //Added the @required annotation here
    
      ...
    }
    

    【讨论】:

    • 您可能会得到一个空列表,因为您的初始数据设置为一个空列表。在_foodListFromSS过滤方法中在snapshot.docs上打断点,看看有没有什么显示。
    • 对给您带来的不便深表歉意。您在答案中回答的内容完美无缺。我刚刚意识到与firebase连接的参数并不相似。但是,我感谢您的帮助!但是我还有一个关于initialData的问题,除了[],我还能输入什么?当我第一次看到initialData时,我很迷茫..
    • 如果你保存了一些以前的数据或一些默认数据来显示给用户,你可以把它放在initialData,这样它就会在它从提供给value的流中获取数据时显示出来StreamProvider.
    • 我看到了.. 所以如果它是一个列表,我可以将 initalData 设置为一个空列表。但是如果它不是一个列表怎么办,它只是一个对象。我可以退货吗?
    • 如果你有一个默认对象或者你不能给它一个值,你可以返回一个默认对象。如果您不给它一个值,这意味着final food = Provider.of&lt;List&lt;Food&gt;&gt;(context); 在获取数据时将为空,因此您可以添加一个空检查以了解何时显示/使用if (food == null) {return CircularProgressIndicator();} else {return Widget();} 之类的数据。
    猜你喜欢
    • 2021-03-19
    • 2021-06-05
    • 2020-07-28
    • 2021-03-10
    • 1970-01-01
    • 2021-07-03
    • 2020-06-26
    • 2021-02-03
    • 2021-11-12
    相关资源
    最近更新 更多