flutter 使用Riverpod和Freezed合并不同的状态

5q4ezhmt  于 2023-05-19  发布在  Flutter
关注(0)|答案(1)|浏览(221)

bounty还有2天到期。回答此问题可获得+100声望奖励。Ruble正在寻找这个问题的更详细的答案:建议一种方便的方法来合并/处理多个状态。

我有一个页面需要两个不同的API调用。
我应用干净的架构来编写代码,并将Riverpod作为状态管理。然后我使用Freezed包Map不同的状态。
如何将不同的状态结合起来?我想要实现的是,只有当两个状态都给予我数据时才发出成功状态,或者如果其中一个是错误,则发出错误状态,否则加载状态。
先谢谢你了。
这是两个State类:

import 'package:freezed_annotation/freezed_annotation.dart';
import '...eatures/profile/domain/entities/user_profile_entity.dart';

part 'user_profile_details_state.freezed.dart';

@freezed
class UserProfileDetailsState with _$UserProfileDetailsState {
  ///Initial
  const factory UserProfileDetailsState.initial() =
      _UserProfileDetailsStateInitial;

  ///Loading
  const factory UserProfileDetailsState.loading() =
      _UserProfileDetailsStateLoading;

  ///Data
  const factory UserProfileDetailsState.data(
      {required ProfileEntity profileEntity}) = _UserProfileDetailsStateData;

  ///Error
  const factory UserProfileDetailsState.error([String? error]) =
      _UserProfileDetailsStateError;
}
import 'package:freezed_annotation/freezed_annotation.dart';
import '....features/profile/domain/entities/user_properties_entity.dart';

part 'user_properties_state.freezed.dart';

@freezed
class UserPropertiesState with _$UserPropertiesState {
  ///Initial
  const factory UserPropertiesState.initial() = _UserPropertiesStateInitial;

  ///Loading
  const factory UserPropertiesState.loading() = _UserPropertiesStateLoading;

  ///Data
  const factory UserPropertiesState.data(
          {required UserPropertiesEntity userPropertiesEntity}) =
      _UserPropertiesStateData;

  ///Error
  const factory UserPropertiesState.error([String? error]) =
      _UserPropertiesStateError;
}

这是两个通知:

import '...core/di/dependency_injection.dart';
import '...core/errors/failures.dart';
import '...core/presentation/riverpod/check_token_notifier.dart';
import '...features/profile/presentation/riverpod/user_profile_details_state.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_profile_details_notifier.g.dart';

@riverpod
class UserProfileDetailsNotifier extends _$UserProfileDetailsNotifier {
  @override
  UserProfileDetailsState build() {
    getUserProfileDetailsData();
    return const UserProfileDetailsState.initial();
  }

  Future<void> getUserProfileDetailsData() async {
    state = const UserProfileDetailsState.loading();
    final userProfileDetailsOrFailure = await ref
        .read(userProfileDetailsUseCaseProvider)
        .getUserProfileDetailsData();
    userProfileDetailsOrFailure.fold((error) {
      if (error is TokenFailure) {
        ref.read(checkTokenNotifierProvider.notifier).deAuthUser();
        return;
      }
      state = UserProfileDetailsState.error(error.errorMessage);
    }, (userProfileDetailsEntity) {
      state =
          UserProfileDetailsState.data(profileEntity: userProfileDetailsEntity);
    });
  }
}
import '...core/di/dependency_injection.dart';
import '...core/errors/failures.dart';
import '...core/presentation/riverpod/check_token_notifier.dart';
import '...features/profile/presentation/riverpod/user_properties_state.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_properties_notifier.g.dart';

@riverpod
class UserPropertiesNotifier extends _$UserPropertiesNotifier {
  @override
  UserPropertiesState build() {
    getUserPropertiesData();
    return const UserPropertiesState.initial();
  }

  Future<void> getUserPropertiesData() async {
    state = const UserPropertiesState.loading();

    final userPropertiesOrFailure =
        await ref.read(userPropertiesUseCaseProvider).getUserPropertiesData();
    userPropertiesOrFailure.fold((error) {
      if (error is TokenFailure) {
        ref.read(checkTokenNotifierProvider.notifier).deAuthUser();
        return;
      }
      state = UserPropertiesState.error(error.errorMessage);
    }, (userPropertiesEntity) {
      state =
          UserPropertiesState.data(userPropertiesEntity: userPropertiesEntity);
    });
  }
}
ubby3x7f

ubby3x7f1#

您可以创建一个单独的@freezed类,其中将根据您的两个状态收集相应的新字段。在代码中,您可以这样做:

state = CommonState.loading();

UserPropertiesState userProperties;
UserProfileDetailsState userProfileDetails;

final CommonState? state = userProperties.whenOrNull(
  orElse: () => null,
  data: (properties) => userProfileDetails.whenOrNull(
      orElse: () => null,
      data: (details) => CommonState.data(properties + details),
  ),
);

if (state == null) {
  // same with repeat with error
}

您可以使用whenOrNull中的必填字段,或拆分为ifs

相关问题