dart 如何在Getx中使用fold而不是reduce?

eagi6jfj  于 2023-06-27  发布在  其他
关注(0)|答案(1)|浏览(133)

我正在使用getx学习一个购物车教程,我遇到了一个问题,当购物车是空的时候,我收到“bad state no element”错误。我知道这是因为.reduce方法在列表为空时会产生这样的错误,但当我尝试使用.fold时,我会得到这样的错误:返回类型'num'不是'int',这是闭包上下文所要求的。
只有一个问题,我发现和我的问题是相同的,但我不明白选择的答案。我一直在寻找答案,但到目前为止,没有一个答案对我有用。
这里是问题的链接:How to identify the List is empty, to avoid the Bad state: No element for ListMixin.reduce
这是我的控制器:

import 'package:get/get.dart';
import 'package:plantel/screens/widgets/product_model.dart';

class CartController extends GetxController {
  final _products = {}.obs;

  void addProduct(Product product) {
    if (_products.containsKey(product)) {
      _products[product] += 1;
    } else {
      _products[product] = 1;
    }
  }

  void removeProduct(Product product) {
    if (_products.containsKey(product) && _products[product] == 1) {
      _products.removeWhere((key, value) => key == product);
    } else {
      _products[product] -= 1;
    }
  }

  get productSubtotal => _products.entries
      .map((product) => product.key.price * product.value)
      .toList();

  get total => _products.entries
      .map((product) => product.key.price * product.value)
      .toList()
      .reduce((value, element) => value + element)
      .toStringAsFixed(2);

  get products => _products;
}

这里是产品控制器,我使用Cloud Firestore数据库来获取列表。

import 'package:get/get.dart';
import 'package:plantel/screens/widgets/firestore_db.dart';
import 'package:plantel/screens/widgets/product_model.dart';

class InDoorProductController extends GetxController {
  final products = <Product>[].obs;

  @override
  void onInit() {
    products.bindStream(FirestoreDB().getInDoorProducts());

    super.onInit();
  }
}

class OutDoorProductController extends GetxController {
  final products = <Product>[].obs;

  @override
  void onInit() {
    products.bindStream(FirestoreDB().getOutdoorProducts());

    super.onInit();
  }
}

class PotsAndVasesProductController extends GetxController {
  final products = <Product>[].obs;

  @override
  void onInit() {
    products.bindStream(FirestoreDB().getpotsandvasesProducts());

    super.onInit();
  }
}

class SoilsProductController extends GetxController {
  final products = <Product>[].obs;

  @override
  void onInit() {
    products.bindStream(FirestoreDB().getsoilsProducts());

    super.onInit();
  }
}

class PesticidesProductController extends GetxController {
  final products = <Product>[].obs;

  @override
  void onInit() {
    products.bindStream(FirestoreDB().getpesticidesProducts());

    super.onInit();
  }
}

下面是用于获取集合的FirestoreDB类。

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:plantel/screens/widgets/product_model.dart';

class FirestoreDB {
  final FirebaseFirestore _firebaseFirestoreindoor = FirebaseFirestore.instance;
  Stream<List<Product>> getInDoorProducts() {
    return _firebaseFirestoreindoor
        .collection('indoorplants')
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
    });
  }

  final FirebaseFirestore _firebaseFirestoreoutdoor =
      FirebaseFirestore.instance;
  Stream<List<Product>> getOutdoorProducts() {
    return _firebaseFirestoreoutdoor
        .collection('outdoorplants')
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
    });
  }

  final FirebaseFirestore _firebaseFirestorepotsandvases =
      FirebaseFirestore.instance;
  Stream<List<Product>> getpotsandvasesProducts() {
    return _firebaseFirestorepotsandvases
        .collection('potsandvases')
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
    });
  }

  final FirebaseFirestore _firebaseFirestoresoils = FirebaseFirestore.instance;
  Stream<List<Product>> getsoilsProducts() {
    return _firebaseFirestorepotsandvases
        .collection('soils')
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
    });
  }

  final FirebaseFirestore _firebaseFirestorepesticides =
      FirebaseFirestore.instance;
  Stream<List<Product>> getpesticidesProducts() {
    return _firebaseFirestorepotsandvases
        .collection('pesticides')
        .snapshots()
        .map((snapshot) {
      return snapshot.docs.map((doc) => Product.fromSnapshot(doc)).toList();
    });
  }
}

这是产品型号

import 'package:cloud_firestore/cloud_firestore.dart';

class Product {
  final String title;
  final int price;
  final String subtitle;
  final String image;

  const Product(
      {required this.title,
      required this.price,
      required this.subtitle,
      required this.image});

  static Product fromSnapshot(DocumentSnapshot snap) {
    Product product = Product(
        title: snap['title'],
        price: snap['price'],
        subtitle: snap['subtitle'],
        image: snap['image']);
    return product;
  }
}

如果我添加了不必要的代码块,我很抱歉,但我添加它们是为了防止有人想了解我是如何获得列表的全貌。

0x6upsns

0x6upsns1#

Fold需要一个初始元素(通常称为累加器),如果列表为空,它也将是“默认”返回值。因此,要将此reduce:

final sum = someList.reduce((a, b) => a + b);

我们只需要提供一个初始值:

final sum = someList.fold(0, (a, b) => a + b);

如果someList为空,则返回0。
只要知道默认值,你总是可以将reduce重写为fold。你也可以反过来使用,将折叠重写为reduce:

final sum = [0, ...someList].reduce((a, b) => a + b);

所以这是另一种写法。:)
(Note但是,这需要初始值与其他元素的类型相同…当累加器是一个完全不同的类型时,fold也可以处理,这使得了解它非常有用。)

相关问题