You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:从Firestore嵌套映射获取IsVegan字段并实现属性匹配

问题描述

我想将当前用户的IsVegan属性与产品的IsVegan属性做匹配,匹配成功显示绿色勾选图标,否则显示红色叉号图标。目前已通过ProductModel实例成功获取产品属性,相关代码如下:

产品卡片代码(product_card_vertical.dart)

Positioned(
  bottom: 0,
  left: 0,
  child: product.productPreferences!.isVegan &&
          // 此处需填入用户的IsVegan属性
      ? NCircularIcon(
          icon: Icons.check_circle,
          color: NColors.primary,
          height: 33,
          width: 30,
          size: 23,
        )
      : NCircularIcon(
          icon: Icons.cancel,
          color: NColors.red,
          height: 33,
          width: 30,
          size: 23,
        ),
),

我尝试通过Firestore查询获取用户属性,编写了以下方法:

Future<UserModel> fetchUserIsVegan() async {
  try {
    final documentSnapshot = await _db
        .collection("Users")
        .doc(AuthenticationRepository.instance.authUser?.uid)
        .get();
    userMap2 = documentSnapshot.data();
    print(userMap2);
    if (documentSnapshot.exists) {
      return UserModel.fromSnapshot(documentSnapshot);
    } else {
      return UserModel.empty();
    }
  } catch (e) {
    throw 'Something went wrong. Please try again';
  }
}

但我无法通过document.get从Firestore的嵌套映射中获取IsVegan布尔值,我的Firestore数据结构为:用户文档下包含userPreferences嵌套字段,该字段内有IsVegan属性。


解决方案

1. 修正UserModel的解析逻辑

首先检查UserModel的fromSnapshot方法,确保正确解析嵌套的userPreferences字段。示例代码如下:

class UserModel {
  final bool isVegan;

  UserModel({required this.isVegan});

  factory UserModel.fromSnapshot(DocumentSnapshot snapshot) {
    final data = snapshot.data() as Map<String, dynamic>;
    // 取出嵌套的userPreferences,为空则返回空Map避免报错
    final userPreferences = data['userPreferences'] as Map<String, dynamic>? ?? {};
    return UserModel(
      // 读取IsVegan,默认值设为false防止空值
      isVegan: userPreferences['IsVegan'] ?? false,
    );
  }

  static UserModel empty() => UserModel(isVegan: false);
}

2. 在Widget中异步获取并匹配属性

在product_card_vertical.dart对应的Widget里,用FutureBuilder异步获取用户数据,再完成属性匹配:

// 替换原有的Positioned子组件
Positioned(
  bottom: 0,
  left: 0,
  child: FutureBuilder<UserModel>(
    future: fetchUserIsVegan(),
    builder: (context, snapshot) {
      // 加载状态显示占位容器
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const SizedBox(width: 30, height: 33);
      }
      // 获取用户IsVegan属性,默认false
      final userIsVegan = snapshot.data?.isVegan ?? false;
      // 匹配产品与用户的属性
      return product.productPreferences!.isVegan && userIsVegan
          ? NCircularIcon(
              icon: Icons.check_circle,
              color: NColors.primary,
              height: 33,
              width: 30,
              size: 23,
            )
          : NCircularIcon(
              icon: Icons.cancel,
              color: NColors.red,
              height: 33,
              width: 30,
              size: 23,
            );
    },
  ),
),

3. 优化数据获取(可选)

如果该卡片会频繁渲染,建议用状态管理工具(如Provider、Riverpod)提前缓存用户数据,避免重复请求Firestore:

// 示例:用Riverpod缓存用户数据
final userProvider = FutureProvider<UserModel>((ref) {
  return ref.watch(firestoreServiceProvider).fetchUserIsVegan();
});

// 在Widget中使用缓存数据
final userAsyncValue = ref.watch(userProvider);
Positioned(
  bottom: 0,
  left: 0,
  child: userAsyncValue.when(
    loading: () => const SizedBox(width: 30, height: 33),
    error: (_, __) => NCircularIcon(
      icon: Icons.cancel,
      color: NColors.red,
      height: 33,
      width: 30,
      size: 23,
    ),
    data: (user) {
      return product.productPreferences!.isVegan && user.isVegan
          ? NCircularIcon(
              icon: Icons.check_circle,
              color: NColors.primary,
              height: 33,
              width: 30,
              size: 23,
            )
          : NCircularIcon(
              icon: Icons.cancel,
              color: NColors.red,
              height: 33,
              width: 30,
              size: 23,
            );
    },
  ),
),

内容的提问来源于stack exchange,提问作者Safwan Norasidin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:45:40