Flutter Bloc copyWith 功能不起作用

问题描述 投票:0回答:1

我正在将 Flutter Bloc 与事件和状态一起使用。 我尝试了多种方法,但 copyWith 函数根本不起作用。 该集团每次都会产生现在状态并重置前一个状态。 如何保留以前的状态..?

我的代码是这样的: 我创建了一个包含多个可以触发的事件的块。

class AddressBloc2 extends Bloc<AddressEvent, AddressState> {
  AddressBloc2() : super(AddressInitial()) {
    on<GetAddressList>(_getAddressList);
    on<GetCurrentLocation>(_getCurrentLocation);
    on<GetGeoAddress>(_getGeoAddress);
    on<AddAddress>(_addAddress);
    on<UpdateAddress>(_updateAddress);
    on<RemoveAddress>(_removeAddress);
    on<SetDefaultAddress>(_setDefaultAddress);
  }

  void _getAddressList(GetAddressList event, emit) async {
    try {
      final response = await AddressServices.getAddressList();
      final Address? defaultAddress = response
          .firstWhereOrNull((element) => element.addressDefault == true);
      emit(AddressLoaded(addresses: response, defaultAddress: defaultAddress));
    } catch (e) {
      emit(AddressError(e.toString()));
    }
  }

  void _getCurrentLocation(GetCurrentLocation event, emit) async {
    if (event.currentLocation == null) {
      logger('this is crashing currentlocation');
    }
    emit(
      const AddressLoaded().copyWith(currentLocation: event.currentLocation),
    );
    logger(state);
  }

  void _getGeoAddress(GetGeoAddress event, emit) async {
    if (state is GetGeoAddressLoading) return;
    emit(GetGeoAddressLoading());
    try {
      Map<String, dynamic> geoAddress =
          await AddressServices.getGeoAddress(event.currentLocation);
      logger('before geoAddress');
      logger(state);
      emit(const AddressLoaded().copyWith(geoAddress: geoAddress));
      logger(state);
    } catch (e) {
      emit(GetGeoAddressError(e.toString()));
      logger(e.toString());
      emit(const AddressLoaded());
    }
  }
}


我的活动文件:

part of 'address_bloc.dart';

sealed class AddressEvent extends Equatable {
  const AddressEvent();
  @override
  List<Object> get props => [];
}

class GetAddressList extends AddressEvent {}

class GetCurrentLocation extends AddressEvent {
  final LatLng currentLocation;

  const GetCurrentLocation(this.currentLocation);

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

class GetGeoAddress extends AddressEvent {
  final LatLng currentLocation;

  const GetGeoAddress(this.currentLocation);

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

我的状态文件是这样的, 因为我正在获取地址,并从 api 加载地址列表并添加和删除地址。我希望它位于单个块文件中。

part of 'address_bloc.dart';

sealed class AddressState extends Equatable {
  const AddressState();

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

class AddressInitial extends AddressState {}

class AddressLoading extends AddressState {}

class AddressLoaded extends AddressState {
  final List<Address> addresses;
  final Address? defaultAddress;
  final LatLng? currentLocation;
  final Map<String, dynamic>? geoAddress;

  const AddressLoaded({
    this.addresses = const [],
    this.defaultAddress,
    this.currentLocation,
    this.geoAddress,
  });

  @override
  List<Object?> get props =>
      [addresses, defaultAddress, currentLocation, geoAddress];

  AddressLoaded copyWith({
    List<Address>? addresses,
    Address? defaultAddress,
    LatLng? currentLocation,
    Map<String, dynamic>? geoAddress,
  }) {
    return AddressLoaded(
      addresses: addresses ?? this.addresses,
      defaultAddress: defaultAddress ?? this.defaultAddress,
      currentLocation: currentLocation ?? this.currentLocation,
      geoAddress: geoAddress ?? this.geoAddress,
    );
  }
}

class AddressError extends AddressState {
  final String error;

  const AddressError(this.error);

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

class GetGeoAddressLoading extends AddressState {}

class GetGeoAddressError extends AddressState {
  final String error;

  const GetGeoAddressError(this.error);
  @override
  List<Object> get props => [error];
}

除此之外,还有多个事件,它们一起需要更新单个 AddressLoaded 文件。

flutter dart state bloc
1个回答
0
投票

您应该使用 copyWith 创建一个与原始对象具有相同属性的新对象,但某些值已更改。所以没有任何感觉这样做:

emit(const AddressLoaded().copyWith(geoAddress: geoAddress));

您创建空的新实例,然后使用 copyWith 创建其他新实例。您可以在此answer中查看更多信息。 如果您确定这个案例是真实的,您可以这样做:

  void _getCurrentLocation(GetCurrentLocation event, emit) async {
    if (event.currentLocation == null) {
      logger('this is crashing currentlocation');
    }
    if (state is AddressLoaded) {
        emit(
         (state as AddressLoaded).copyWith(currentLocation: event.currentLocation),
         );
    }
    logger(state);

}

但是这里它不适用于复制,因为您在检索数据时声明为 GetGeoAddressLoading 。因此,您可以创建新的 stte,如果您需要一些数据,您可以在将状态更改为加载之前预先提取数据:

void _getGeoAddress(GetGeoAddress event, emit) async {
    if (state is GetGeoAddressLoading) return;
final currentLocation = state is AddressLoaded? (state as AddressLoaded).AddressLoaded : null;
    //..other data
    emit(GetGeoAddressLoading());
    try {
      Map<String, dynamic> geoAddress =
          await AddressServices.getGeoAddress(event.currentLocation);
      logger('before geoAddress');
      logger(state);
      emit(const AddressLoaded(
             currentLocation: currentLocation,
             //..other data
             geoAddress: geoAddress));
      logger(state);
    } catch (e) {
      emit(GetGeoAddressError(e.toString()));
      logger(e.toString());
      emit(const AddressLoaded());
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.