Flutter - BloC Cubit 函数不发出状态

use*_*566 2 android flutter bloc

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

我写了一段代码:

我的物品 肘节

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

  void addItem(item){
    state.add(item);
    emit(state);
  }
}
Run Code Online (Sandbox Code Playgroud)

提供者的项目页面

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

我在 Stateless Widget 中调用 BlocBuilder,如下所示:

body: BlocBuilder<MarketCubit, List<Market>>(
            builder: (context, items) => TabBarView(...))
Run Code Online (Sandbox Code Playgroud)

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

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


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

ListView 不更新。什么问题?多谢!

Kri*_*ris 5

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

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

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

emit([...state, newValue])
Run Code Online (Sandbox Code Playgroud)

或者

final newList = List.from(state)..add(newValue);
emit(newList);
Run Code Online (Sandbox Code Playgroud)

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

本质上,状态应该是“不可变的”,所以如果你要发出一个新状态,你实际上应该为你要发出的任何东西创建一个新实例。我通常使用状态的方式是为 cubit 正在跟踪的任何状态提供一个带有最终字段的类,以及一个 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,
        );   

}
Run Code Online (Sandbox Code Playgroud)

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