我正在使用flutter_bloc
库开发用于状态管理的Web应用程序。在我的应用程序中,我必须跟踪表单(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
软件包进行相等性比较,但是我真的不明白我哪里错了。
答案 0 :(得分:0)
使用Equatable,您必须具有不可变的字段(您的列表是可修改的)。
类似的事情我想:
final someList = <int>[1, 2, 3]; // this is done when creating state
final anotherList = someList; // this is done with update, you just pass the reference
someList.add(4);
print(anotherList == someList); // true
所以等价,它检查通过的props
是否相等(在这种情况下相等)。
解决方案:
Stream<AreaFormState> _mapSpecialitaAddedToState(
Specialita specialita,
) async* {
// creating a new copy of the list
yield state.update(
listaSpecialita: List<Specialita>.of(
state.listaSpecialita..add(specialita),
),
);
}
这为列表提供了具有相同值的新引用。 这将使内部==检查为false。
除非它们不相等,否则Bloc不会发出新状态。
建议您改用freezed软件包,这样可以节省您 copyWith的麻烦。
答案 1 :(得分:0)
我使用Dart的 spread运算符解决了该问题:
let tags = ["12345"]