Обновление значения в списке Cubit Flutter

#flutter #dart #bloc

#flutter #dart #блок

Вопрос:

В приложении я использую Cubit. ItemData извлекается из firestore. Все работает, но после добавления элемента в список и обновления значения (имени) в firestore в списке остается старое значение. Как это решить?

  class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          BlocBuilder<ItemCubit, ItemState>(
            cubit: ItemCubit(DataBase())..getItemData(item),
            builder: (context, state) {
              if (state is ItemData) {
                return Column(
                  children: [
                    Text(state.item.name),
                    RaisedButton(
                      onPressed: () {
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => TestPage1(
                                      item: state.item,
                                    )));
                      },
                      child: Text('showPage'),
                    ),
                    RaisedButton(
                      onPressed: () {
                        context.bloc<TestCubit>().add(item);
                      },
                    )
                  ],
                );
              }
              return Container(
                child: Text('error'),
              );
            },
          )
        ],
      ),
    );
  }
}
  

для добавления элемента в список я использую другой
код cubit:

 class AddCubit extends Cubit<AddState> {
  AddCubit() : super(AddInitial());
  List<Item> items = List<Item>();

  void addItem(Item item) {
    items.add(item);
    emit(LoadList(items));
  }
}
  

Это блок для получения списка элементов в TestPage1:

   BlocBuilder<AddCubit, AddState>(builder: (context, state) {
          if (state is LoadList) {
            return Column(
              children: state.items.toSet().map((item) {
                return Card(
                  child: Text(item.name),
                );
              }).toList(),
            );
          }
        })
  

код состояния:

 class LoadList extends AddState {
  final List<Item> items;

  LoadList(this.items);
}
  

Ответ №1:

В flutter при сравнении двух объектов одного и того же класса у вас всегда будет равенство, даже если их значения различны. Если только вы не будете использовать метод равенства в своем классе.

Код класса с методом равенства

 import 'package:equatable/equatable.dart';

class LoadList extends AddState {
  final List<Item> items;

  LoadList(this.items);
  @override
  List<Object> get props => [items];
}
  

Второе — это тот факт, что вы должны использовать copy with и не создавать новое состояние для нового значения. Это пригодится позже и уменьшит количество возможных ошибок в дальнейшем.

Весь код для класса состояния

 import 'package:equatable/equatable.dart';

class LoadList extends AddState {
  final List<Item> items;
  LoadList(this.items);

  LoadList copyWith({
    List<Item> items,
  }) {
    return LoadList(
      items: items?? this.items,
    );
  }

  @override
  List<Object> get props => [items];
}
  

И затем для вашей функции void вы должны использовать:

 void addItem(Item item) {
    items.add(item);
    emit(state.copyWith(items: items);
 }
  

Ответ №2:

просто к вашему сведению. Приведенный выше ответ не будет работать на 100%, если вы пытаетесь обновить свой виджет, потому что List.add немедленно обновит состояние (но не будет вызывать Bloc или Cubit из-за того, что Equatable сравнивает значения).

Поэтому, если вы хотите использовать List.add или List.remove, вам просто нужно где-то выполнить setState .