简体   繁体   English

ListView 中的有状态小部件未更新

[英]Stateful Widget in a ListView is not getting updated

I have a list of all deals _deals and a list of selected deals _selectedDeals .我有所有交易的列表_deals和选定交易的列表_selectedDeals Deals can be added to or removed from the list _selectedDeals from another class. So if a new deal is added/removed, I want to rebuild this DealsWidget so the newly added/removed deal is properly reflected in UI.交易可以添加到另一个 class 的_selectedDeals列表中或从列表中删除。因此,如果添加/删除新交易,我想重建此DealsWidget ,以便新添加/删除的交易正确反映在 UI 中。

And I'm using BookButton stateful widget, to show if a deal is selected or not.我正在使用BookButton有状态小部件,以显示是否选择了交易。 When isBooked is true, it means that the deal is selected.isBooked为真时,表示已选择交易。

I planned to achieve this behavior by calling the refresh() function of DealsWidget after data is added/removed from that other class so it would rebuild everything and my UI is consistent with data, but nothing happened.我计划通过在从另一个 class 添加/删除数据后调用DealsWidgetrefresh() function 来实现此行为,这样它将重建所有内容并且我的 UI 与数据一致,但没有任何反应。

What I've found out is that rebuilding won't recreate BookButton widgets again.我发现重建不会再次重新创建BookButton小部件。 Their constructors are not called again.他们的构造函数不再被调用。 And that is why my updated value is not getting entertained, because I'm passing them in constructor of BookButton .这就是为什么我的更新值没有得到接受,因为我将它们传递给BookButton的构造函数。

Can anyone explain why is this happening and how can I properly show which deals are selected and which are not?任何人都可以解释为什么会发生这种情况以及我如何正确显示选择了哪些交易而没有选择哪些交易?

DealsWidget交易小部件

class DealsWidget extends StatefulWidget {

  final List<Deal> _deals;
  final List<Deal> _selectedDeals;

  final DealSelectionListener _dealSelectionListener;

  DealsWidget(
    Key dealsKey,
    this._deals,
    this._selectedDeals,
    this._dealSelectionListener,
  ) : super(key: dealsKey);

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

class DealsWidgetState extends State<DealsWidget> {

  @override
  Widget build(BuildContext context) {

    final totalDeals = widget._deals.length;

    return ListView.builder(
      physics: NeverScrollableScrollPhysics(),
      itemCount: totalDeals,
      shrinkWrap: true,
      itemBuilder: (context, index) {

        final deal = widget._deals[index];
        final isSelected = widget._selectedDeals.contains(deal);
        
        return Container(
          color: Colors.white,
          padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
          child: BookButton(
            isSelected,
            (isBooked) {
              if (isBooked) {
                widget._dealSelectionListener._onSelected(deal);
              } else {
                widget._dealSelectionListener._onDeselected(deal);
              }
            }
          ),
        );
      }
    );
  }

  void refresh() {

    print('Refreshing deals');

    setState(() {
      
    });
  }
}

BookButton图书按钮

class BookButton extends StatefulWidget {

  final bool isBooked;
  final OnBookChangedListener listener;

  BookButton(this.isBooked, this.listener);

  @override
  BookButtonClass createState() => BookButtonClass(isBooked);
}
  
class BookButtonClass extends State<BookButton> {

  bool isBooked;

  BookButtonClass(this.isBooked);

  void check(bool check) {
    setState(() {
      isBooked = check;
      widget.listener.call(isBooked);
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: (){
        setState(() {
          isBooked = !isBooked;
          widget.listener.call(isBooked);
        });
      },
      child: Text(
        isBooked ? AppStrings.unbook.toUpperCase() : AppStrings.book.toUpperCase(),
        style: TextStyle(
          color: isBooked ? AppColors.accentColor : Colors.white,
          fontSize: 12,
        ),
      ),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(5),
        side: BorderSide(
          color: AppColors.accentColor,
          width: isBooked ? 1 : 0,
        )
      ),
      color: isBooked ? Colors.transparent : AppColors.accentColor,
    );
  }
}

in this case you should use a Provider, becouse the widget needs to known when to rebuild.在这种情况下,您应该使用 Provider,因为小部件需要知道何时重建。

Or if you think that Provider its kind of hard to learn now, try using a SetState() on your event ClickButton, this shoud resolve或者,如果您认为 Provider 现在很难学习,请尝试在事件 ClickButton 上使用 SetState(),这应该可以解决

Look what i did in my Case看看我在我的案例中做了什么

So in my class with the data i used a the change changeNotifier所以在我的 class 和数据中,我使用了 change changeNotifier

class PartnerControler extends ChangeNotifier {
....
changeNotifiers()
}

in the display class i used this在显示 class 中我使用了这个

ChangeNotifierProvider(
                  create: (context) => partnerControler,
                  child: buildPartnerList(context),
                ),

 Widget buildPartnerList(BuildContext context) {
return Column(
      children: <Widget>[
Consumer<PartnerControler>(
          builder: (context, partnercontroler, child) {
return (Expanded(
              child: ListView.builder(
itemCount: partnerControler.partnerListFiltered.length,
..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM