繁体   English   中英

Flutter - BloC Cubit function 不发射 state

[英]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.

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