【问题标题】:Flutter - BloC Cubit function doesn't emitting stateFlutter - BloC Cubit 功能不会发出状态
【发布时间】:2022-01-21 11:23:20
【问题描述】:

我正在创建一个 Flutter 应用程序。我在我的项目中添加了一个 BloC 用于管理状态。 我创建了一个包含数据的列表。我想使用按钮“添加”手动将项目添加到 ListView。

我写了一个代码:

我的物品肘

class ItemCubit extends Cubit<List<Item>> {
  ItemCubit() : super([]);

  void addItem(item){
    state.add(item);
    emit(state);
  }
}

提供者的项目页面

class SearchPage extends StatelessWidget {
  const SearchPage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (_) => ItemCubit(),
        child: Search(),
      ),
    );
  }
}

我在 Stateless Widget 中这样调用 BlocBuilder:

body: BlocBuilder<MarketCubit, List<Market>>(
            builder: (context, items) => TabBarView(...))

所以当我从状态调用我的函数时:

Item item = Item(1, 'Item 1');


ElevatedButton(onPressed:(){
  context.read<ItemCubit>().addItem(item);
 }, child: Text('Add Item')),

ListView 没有更新。什么问题? 非常感谢!

【问题讨论】:

    标签: android flutter bloc


    【解决方案1】:

    ItemCubit 类超类没有持有你的状态。你应该管理自己的状态。所以,我所说的,我是说在 ItemCubit 类中创建列表变量,每次调用 addItem 方法都会将项目添加到这个列表并发出这个列表。

    您的 Cubit 类应如下所示;

    abstract class ItemState {
      const ItemState();
    }
    
    class ItemInitial extends ItemState {
      const ItemInitial();
    }
    
    class ItemStateUpdatedList extends ItemState {
      const ItemStateUpdatedList({required this.list});
    
      final List<Item> list;
    }
    
    class ItemCubit extends Cubit<ItemState> {
      ItemCubit() : super(const ItemInitial());
      
      final List<Item> myItemList = [];
    
      void addItem(item){
        myItemList.add(item);
        emit(ItemStateUpdatedList(list: myItemList));
      }
    }
    
    body: BlocBuilder<ItemCubit, ItemState>(
              builder:(context, state) {
                if(state is ItemStateUpdatedList){
                  final list = state.list;
                  return TabBarView(...);
                }
                return const SizedBox.shrink();
              },
    )
    

    【讨论】:

    • 谢谢。是工作。但 ListView 没有更新。
    • 为了了解Cubit的状态已经更新,实例需要改变。您应该以这种方式使用抽象类结构。 (更新了我的答案)
    • 萨利赫可以,谢谢!我运行了你的脚本。但是状态是 ItemStateUpdatedList 返回 false。该脚本返回 SizedBox.shrink();我做错了什么?
    • @user467566 你可以试试 DartPad:dartpad.dev/?id=51ef214e36ced547ecbe3a317d060899
    【解决方案2】:

    问题在于您只是将项目添加到状态并重新发出相同的(修改后的)列表。当你调用 emit() 时,Bloc 本质上会检查状态对象的值,看它是否是一个新对象,如果它是与最后一个状态“相同的列表”,它将什么也不做。这很令人困惑,因为即使您向列表添加了一个新值,它在某种意义上仍然是同一个对象,只是带有一个新值。

    因此,如果您只是创建一个新列表而不是修改原始列表并发出它,那么应该有一个简单的解决方法。

    例如,这应该可以解决问题:

    emit([...state, newValue])
    

    final newList = List.from(state)..add(newValue);
    emit(newList);
    

    (我在 bloc 文档中找不到解释这一点的地方,但有许多问题线程在讨论它 - https://github.com/felangel/bloc/issues/2374)

    从本质上讲,状态应该是“不可变的”,所以如果你要发出一个新的状态,你实际上应该为你要发出的任何东西创建一个新的实例。我通常使用 state 的方式是为 cubit 跟踪的任何状态创建一个带有 final 字段的类,以及一个可以轻松创建具有任何修改字段的新实例的 copyWith 方法:

    YourCubitState{
        final List stateList;
        final otherField;
    
        const YourCubitState({
            this.stateList = [], 
            this.otherField,
        }); 
    
        YourCubitState copyWith({
            List? stateList,
            otherField,
        }) => 
            YourCubitState(
               stateList: stateList ?? this.stateList,
               otherField: otherField ?? this.otherField,
            );   
    
    }
    

    如果状态只是一个列表,这可能是不必要的,但如果您发现自己想要向状态添加属性,那么这是一个很好的模式。

    【讨论】:

    • 谢谢)但这对我不起作用。我认为问题不在此。
    • 'same object' 声明是金,谢谢。
    猜你喜欢
    • 2020-02-21
    • 2021-12-23
    • 2023-01-05
    • 2020-01-14
    • 2021-01-10
    • 2021-06-20
    • 2021-03-13
    • 2021-09-03
    • 2021-12-14
    相关资源
    最近更新 更多