簡體   English   中英

在我的 flutter 有狀態小部件中獲取 Future 變量的正確方法是什么

[英]What is the proper way to fetch a Future variable within my flutter stateful widget

如何確保我的 batchNo 在我的 for 循環中的每次迭代中得到更新? 我對解決這個問題的“正確”方法感到困惑。 我猜我應該在本地初始化 batchNo 並將其更新為 go 而不是每次調用 loadAndUploadCsvData() 時都獲取它。 我嘗試在我的 initState() 中聲明一個本地 _batchNo 但我不確定如何訪問這個變量。 我嘗試在我的 _TestUploadState 中創建一個 localVariable,但我不確定如何在 Widget 構建中更新變量,因為它不是未來的構建。

發生了什么:batchNo 不會在 for 循環中的每次迭代中得到更新,因此數據全部存儲在一個文檔中。 batchNo 從 firebase 獲取(即 batchNo = 1),在循環的第二次迭代時 batchNo 保持 1 並且可能由於缺少 await 關鍵字而未更新。

預期:我希望在 for 循環中的每次迭代中更新 batchNo,因此每次迭代都會創建一個單獨的文檔。 batchNo 從 firebase 獲取(即 batchNo = 1),在循環的第二次迭代中 batchNo 得到更新並且 batchNo = 2。

class TestUpload extends StatefulWidget {
  const TestUpload({super.key});

  @override
  _TestUploadState createState() => _TestUploadState();
}

class _TestUploadState extends State<TestUpload> {
  Widget build(BuildContext context) {
    
    // batchNo not updating within for loop
    for (BatchData batchData in _batchDataList) {
      loadAndUploadCsvData(batchData.name, batchData.bytes);
    }
  }

  void loadAndUploadCsvData(String name, Uint8List? bytes) async {

    // First batchNo call is not updated on subsequent batchNo
    int batchNo = await getNextBatchNo();

    // Send current batch to firebase
    FirebaseFirestore.instance
        .collection('availableBatches')
        .doc("batch" "$batchNo")
        .set({"batchNo": batchNo});
  }

  // Gets next batch no from firebase from document names
  Future<int> getNextBatchNo() async {
    QuerySnapshot batchCollection = await FirebaseFirestore.instance
        .collection('availableBatches')
        .orderBy('batchNo', descending: true)
        .get();

    // If collection doesn't exist
    if (batchCollection.docs.isEmpty) {
      return 1;
    }

    int batchNo = batchCollection.docs[0].get('batchNo');

    return batchNo + 1;
  }

}

我試過這樣做

class TestUpload extends StatefulWidget {
  const TestUpload({super.key});

  @override
  _TestUploadState createState() => _TestUploadState();
}

class _TestUploadState extends State<TestUpload> {
  int _batchNo = 1;

  int iteration = 0;

  final List<BatchData> _batchDataList = [];

  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          padding: EdgeInsets.all(8),
          child: Column(
            children: [
              const SizedBox(
                height: 12,
              ),
              ElevatedButton(
                  onPressed: () {
                    for (BatchData batchData in _batchDataList) {
                      loadAndUploadCsvData(batchData.name, batchData.bytes);
                      log("iteration: $iteration");
                      iteration++;
                      log("_batchNo: $_batchNo");
                      updateBatchNo();
                    }
                  },
                  child: Text("TESTING")),
            ],
          )),
    );
  }

  void loadAndUploadCsvData(String name, Uint8List? bytes) async {
    String extension = name.split('.').last;

    int batchNo = await getNextBatchNo();

    if (extension == 'xls' || extension == "xlsx") {

      // Do some xls xlsx manipulation
      var excel = Excel.decodeBytes(bytes!);

      for (var table in excel.tables.keys) {
        for (var row in excel.tables[table]!.rows) {
          ContactModel currentContact;

          // Skip first (header) row
          if (row[0]!.colIndex == 0 && row[0]!.rowIndex == 0) {

            continue;
          }
          // Create currentContact Model
          currentContact = ContactModel(
              name: row[0]!.value,
              number: row[1]!.value,
              type: row[2]!.value,
              isCalled: false);

          // Send current batch to firebase
          _firestore
              .collection('availableBatches')
              .doc("batch" "$batchNo")
              .set({"batchNo": batchNo});

          // Send current contact to firebase
          _firestore
              .collection('availableBatches')
              .doc("batch" "$batchNo")
              .collection("batchCollection")
              .add(currentContact.toMap());
        }
      }
    }
  }

  Future<int> getNextBatchNo() async {
    QuerySnapshot batchCollection = await FirebaseFirestore.instance
        .collection('availableBatches')
        .orderBy('batchNo', descending: true)
        .get();

    // If collection doesn't exist
    if (batchCollection.docs.isEmpty) {
      setState(() {
        _batchNo = 1;
      });
      return 1;
    }

    int batchNo = batchCollection.docs[0].get('batchNo');

    setState(() {
      _batchNo = batchNo + 1;
    });

    return batchNo + 1;
  }

  void updateBatchNo() async {
    int batchNo = await getNextBatchNo();
    setState(() {
      _batchNo = batchNo;
    });
  }
}

但是仍然在嘗試通過我的循環將我的詳細信息發送到 firestore 時

[log] iteration: 0
[log] _batchNo: 1
[log] iteration: 1
[log] _batchNo: 1

通過將我的void loadAndUploadCsvData(String name, Uint8List? bytes)返回類型更改為Future<void> loadAndUploadCsvData(String name, Uint8List? bytes)並在每次迭代前調用await解決了這個問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM