Flutter: функция setState() неправильно обновляет значение

У меня есть приложение Flutter, где функция setState() вызывается внутри функции loadExpenses() сразу после метода запроса к базе данных. изначально счет списка расходов (expCount) устанавливается равным 0. Позже, в зависимости от выбора фонда, список расходов обновляется, и, следовательно, expCount обновляется, чтобы ListView.builder () мог правильно обновить представление списка. Тем не менее, я могу заметить, что после выбора фонда из фонда dropDownMenu расходный список корректно обновляется в функции loadExpenses(). Но this.expCount = _expenses.length; не обновляет значение expCount, и поэтому ListView Builder не может создать список.

this.dbHelper.getExpensesByFundId (this._selectedFund.id).then ((список расходов) { setState(() { this._expenses = расходы; this.expCount = _expenses.length;

 });

Однако, если я возьму эту строку за пределы функции setState(), я увижу, что переменная expCount обновляется просто find. Можете ли вы сказать мне, в чем здесь проблема?

Вот мой код:

import 'package:flutter/material.dart';
import 'package:ksk_tavel_exp/Models/expense.dart';
import 'package:ksk_tavel_exp/Models/fund.dart';
import 'package:ksk_tavel_exp/utils/dbHelper.dart';

class ExpenseList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ExpenseListState();
  }
}

class ExpenseListState extends State<ExpenseList> {
  List<Fund> _funds;
  List<Expense> _expenses;
  Fund _selectedFund;
  int expCount = 0;

  DatabaseHelper dbHelper = DatabaseHelper();

  loadFunds() {
    if (this._selectedFund == null) {
      this.dbHelper.getFunds().then((List<Fund> funds) {
        setState(() {
          this._funds = funds;
          this._selectedFund = this._funds[0];
          this.loadExpenses();
        });
      });
    }
  }

  loadExpenses() {
    this
        .dbHelper
        .getExpensesByFundId(this._selectedFund.id)
        .then((List<Expense> expenses) {
      setState(() {
        this._expenses = expenses;
        this.expCount = _expenses.length;

     });
    });

  }

  Widget expenseBuilder(BuildContext context, int index) {
    return ListTile(
      leading: Text(this._expenses[index].date),
      title: Text(this._expenses[index].expense),
      trailing: Text('${this._expenses[index].amount} BDT'),
    );
  }

  @override
  Widget build(BuildContext context) {
    double screenHeight = MediaQuery.of(context).size.height;
    this.loadFunds();
//    this.loadExpenses();

    return Scaffold(
      appBar: AppBar(
        title: Text('KSK Expense App'),
        elevation: 1.0,
      ),
      body: Column(
        children: <Widget>[
          this._funds != null && this._selectedFund != null
              ? getFunds(screenHeight)
              : Container(),
          this._expenses != null ? this.getExpenses(screenHeight) : Container()
        ],
      ),
    );
  }

  Container getFunds(double screenHeight) {
    return Container(
      height: screenHeight*0.05,
      child: ListTile(
        leading: Text('Fund'),
        title: DropdownButton<Fund>(
          items: _funds.map((Fund item) {
            return DropdownMenuItem<Fund>(
              value: item,
              child: Text(item == null ? '' : item.fundName),
            );
          }).toList(),
          onChanged: (Fund selectedFund) {
            this._selectedFund = selectedFund;
            this.loadExpenses();
            this.expCount = _expenses.length;
          },
        ),
      ),
    );
  }

  Widget getExpenses(double screenHeight) {
    return Container(
        height: screenHeight*0.80,
      child: ListView.builder(
        itemBuilder: this.expenseBuilder,
        itemCount: this.expCount,
      ),
    );
  }

}

1 ответ

Нет необходимости включать this.expCount = _expenses.length;внутри setState(), его можно использовать на ListView.builder()непосредственно, поскольку виджеты будут перестроены после вызова setState().

      ListView.builder(
  itemBuilder: this.expenseBuilder,
  itemCount: _expenses.length,
),

Я также нахожу странным видеть необходимость обновления expCountпосле звонка loadExpenses()внутри DropdownButton.onChanged()

Другие вопросы по тегам