[英]Flutter - BloC Cubit function doesn't emitting state
我正在创建一个 Flutter 应用程序。 我在我的项目中添加了一个 BloC 以进行管理 state。我创建了一个包含数据的列表。 我想使用“添加”按钮手动将项目添加到 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(...))
因此,当我从 state 拨打我的 function 时:
Item item = Item(1, 'Item 1');
ElevatedButton(onPressed:(){
context.read<ItemCubit>().addItem(item);
}, child: Text('Add Item')),
ListView 不更新。 什么问题? 非常感谢!
创建新变量,将它们添加到新变量列表中,将新变量列表项更新到它,使用新变量发出数据。 这就是我让它工作的方式。
late List<ServicesExpensesList> newList = <ServicesExpensesList>[];
state.utilityDataList.forEach((element) {
newList.add(element);
});
newList.insert(0, utilityData);
newList.sort((a, b) => b.createdAt.compareTo(a.createdAt));
emit(state.copyWith(
utilityDataList: newList,
status: state.status == BlocStateStatus.success
? BlocStateStatus.updated
: BlocStateStatus.success,
))
Cubit 或 block 是一个state change emitter ,并且由于 state 是一组属性和特性,这里的关键是 Cubit 和 Bloc 能够弄清楚某些东西已经被属性或属性改变,否则不会发射新的 state .
这对我来说是这样的:
abstract class ObjectListState extends Equatable {
`final List<String> items;
const ObjectListState(this.items);
}
class ObjectListStateInitial extends ObjectListState {
const ObjectListStateInitail(super.items);
@override
List<Object> get props => [];
}
class ObjectListStateItemAdded extends ObjectListState {
final String item;
final List<String> items;
ObjectListStateItemAdded( this.item, this.items) : super(items){
items.add(item);
}
@override
List<Object> get props => [item,items];
}
问题是您只是将项目添加到 state 并重新发出相同的(修改后的)列表。 Bloc will essentially check the value of the state object to see if it is a new object when you call emit(), if it is the 'same list' as the last state, it will do nothing. 这是令人困惑的,因为即使您在列表中添加一个新值,它在某种意义上仍然是相同的 object,只是带有一个新值。
因此,如果您只是创建一个新列表而不是修改原始列表并发出它,那么应该有一个简单的解决方法。
例如,这应该可以解决问题:
emit([...state, newValue])
或者
final newList = List.from(state)..add(newValue);
emit(newList);
(我在 bloc 文档中找不到解释这一点的地方,但有许多问题线程在讨论它 - https://github.com/felangel/bloc/issues/2374)
从本质上讲,state 应该是“不可变的”,所以如果你要发出一个新的 state,你实际上应该为你要发出的任何东西创建一个新实例。 我通常使用 state 的方式是使用 class 的最终字段,用于任何 state 肘正在跟踪的任何字段,以及使用任何修改字段的 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,
);
}
如果 state 只是一个列表,那么这可能是不必要的,但是如果您发现自己想要向 state 添加属性,那么这是一个很好的模式。
ItemCubit class 超类不包含您的 state。 你应该管理自己的状态。 所以,我所说的,我是说在 ItemCubit class 中创建列表变量,并且每次调用 addItem 方法都将项目添加到此列表并发出此列表。
您的 Cubit class 应如下所示;
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();
},
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.