Я разрабатываю веб-приложение, использующее flutter_bloc
библиотеку для управления состоянием. В моем приложении я должен отслеживать состояние формы (виджет AreaForm
). В этой форме я должен управлять списком объектов: я должен иметь возможность добавлять или удалять объект в список.
Это код для AreaFormState:
part of 'area_form_bloc.dart';
class AreaFormState extends Equatable {
final Provincia provincia;
final Comune comune;
final String denominazione;
final List<TipoUdo> listaTipoUdo;
final List<Specialita> listaSpecialita;
final bool isDisciplineChecked;
final bool isBrancheChecked;
final String indirizzo;
const AreaFormState({
@required this.provincia,
@required this.comune,
@required this.denominazione,
@required this.listaTipoUdo,
@required this.listaSpecialita,
@required this.isDisciplineChecked,
@required this.isBrancheChecked,
@required this.indirizzo,
});
factory AreaFormState.empty() {
return AreaFormState(
provincia: null,
comune: null,
denominazione: null,
listaTipoUdo: <TipoUdo>[],
listaSpecialita: <Specialita>[],
isDisciplineChecked: false,
isBrancheChecked: false,
indirizzo: null,
);
}
AreaFormState update({
Provincia provincia,
Comune comune,
String denominazione,
List<TipoUdo> listaTipoUdo,
List<Specialita> listaSpecialita,
bool isDisciplineChecked,
bool isBrancheChecked,
String indirizzo,
}) {
return copyWith(
provincia: provincia,
comune: comune,
denominazione: denominazione,
listaTipoUdo: listaTipoUdo,
listaSpecialita: listaSpecialita,
isDisciplineChecked: isDisciplineChecked,
isBrancheChecked: isBrancheChecked,
indirizzo: indirizzo,
);
}
AreaFormState copyWith({
Provincia provincia,
Comune comune,
String denominazione,
List<TipoUdo> listaTipoUdo,
List<Specialita> listaSpecialita,
bool isDisciplineChecked,
bool isBrancheChecked,
String indirizzo,
}) {
return AreaFormState(
provincia: provincia ?? this.provincia,
comune: comune ?? this.comune,
denominazione: denominazione ?? this.denominazione,
listaTipoUdo: listaTipoUdo ?? this.listaTipoUdo,
listaSpecialita: listaSpecialita ?? this.listaSpecialita,
isDisciplineChecked: isDisciplineChecked ?? this.isDisciplineChecked,
isBrancheChecked: isBrancheChecked ?? this.isBrancheChecked,
indirizzo: indirizzo ?? this.indirizzo,
);
}
@override
List<Object> get props => [
provincia,
comune,
denominazione,
listaTipoUdo,
listaSpecialita,
isDisciplineChecked,
isBrancheChecked,
indirizzo,
];
@override
String toString() {
return '''
AreaFormState {
provincia: $provincia,
comune: $comune,
denominazione: $denominazione,
listaTipoUdo: $listaTipoUdo,
listaSpecialita: $listaSpecialita,
isDisciplineChecked: $isDisciplineChecked,
isBrancheChecked: $isBrancheChecked,
indirizzo: $indirizzo,
}''';
}
}
Это код для AreaFormEvent (я сообщил только о двух интересующих событиях):
part of 'area_form_bloc.dart';
abstract class AreaFormEvent extends Equatable {
const AreaFormEvent();
@override
List<Object> get props => [];
}
...
class SpecialitaAdded extends AreaFormEvent {
final Specialita specialita;
const SpecialitaAdded({@required this.specialita});
@override
List<Object> get props => [specialita];
@override
String toString() => 'SpecialitaAdded { specialita: $specialita }';
}
class SpecialitaRemoved extends AreaFormEvent {
final Specialita specialita;
const SpecialitaRemoved({@required this.specialita});
@override
List<Object> get props => [specialita];
@override
String toString() => 'SpecialitaRemoved { specialita: $specialita }';
}
...
И, наконец, это код для AreaFormBloc:
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import '../../../data/comune.dart';
import '../../../data/provincia.dart';
import '../../../data/specialita.dart';
import '../../../data/tipo_udo.dart';
import '../../repositories/area/area_repository.dart';
part 'area_form_event.dart';
part 'area_form_state.dart';
class AreaFormBloc extends Bloc<AreaFormEvent, AreaFormState> {
final AreaRepository areaRepository;
AreaFormBloc({@required this.areaRepository})
: assert(areaRepository != null);
@override
AreaFormState get initialState => AreaFormState.empty();
@override
Stream<AreaFormState> mapEventToState(
AreaFormEvent event,
) async* {
if (event is ProvinciaSelected) {
yield* _mapProvinciaSelectedToState(event.provincia);
} else if (event is ComuneSelected) {
yield* _mapComuneSelectedToState(event.comune);
} else if (event is DenominazioneChanged) {
yield* _mapDenominazioneChangedToState(event.denominazione);
} else if (event is TipoUdoAdded) {
yield* _mapTipoUdoAddedToState(event.tipoUdo);
} else if (event is TipoUdoRemoved) {
yield* _mapTipoUdoRemovedToState(event.tipoUdo);
} else if (event is SpecialitaAdded) {
yield* _mapSpecialitaAddedToState(event.specialita);
} else if (event is SpecialitaRemoved) {
yield* _mapSpecialitaRemovedToState(event.specialita);
} else if (event is DisciplineChanged) {
yield* _mapDisciplineChangedToState();
} else if (event is BrancheChanged) {
yield* _mapBrancheChangedToState();
} else if (event is IndirizzoChanged) {
yield* _mapIndirizzoChangedToState(event.indirizzo);
} else if (event is NearestUdoIconPressed) {
yield* _mapNearestUdoIconPressedToState();
} else if (event is PulisciPressed) {
yield* _mapPulisciPressedToState();
} else if (event is CercaPressed) {
yield* _mapCercaPressedToState();
}
}
...
Stream<AreaFormState> _mapSpecialitaAddedToState(
Specialita specialita,
) async* {
yield state.update(listaSpecialita: state.listaSpecialita..add(specialita));
}
Stream<AreaFormState> _mapSpecialitaRemovedToState(
Specialita specialita,
) async* {
yield state.update(
listaSpecialita: state.listaSpecialita..remove(specialita));
}
...
}
Таким образом, когда событие SpecialitaAdded
добавляется к AreaFormBloc
, блок должен произвести Переход к новому AreaFormState
, который должен иметь listaSpecialita
, равный предыдущему, с добавлением только что добавленного нового объекта Specialita
.
К сожалению, переход вообще не запускается! Но действительно странно то, что если я добавлю вместо этого такой элемент:
Stream<AreaFormState> _mapSpecialitaAddedToState(
Specialita specialita,
) async* {
yield state.update(listaSpecialita: state.listaSpecialita + [specialita]);
}
затем срабатывает переход.
К сожалению, я не могу сохранить это решение, потому что не знаю, как управлять удалением элемента.
Думаю, проблема в том, что я использую пакет Equatable
для сравнения на равенство, но я действительно не понимаю, в чем я ошибаюсь.