状态不佳:迁移到 flutter_bloc v8.0.1

Sye*_*lal 0 url-rewriting flutter bloc flutter-bloc

我正在尝试解决与 Flutter Bloc 相关的问题。我正在编辑其他人的代码以使其与最新的 flutter_bloc 版本一起使用,但我无法这样做。有人可以重写我的代码以便我可以运行它吗?我看到了很多答案,但我无法理解如何修复我自己的代码。

这是 all_categories_bloc.dart 的完整代码

    class AllCategoriesBloc extends Bloc<AllCategoriesEvent, AllCategoriesState> {
  AllCategoriesBloc({
    this.apiRepository,
  }) : super(AllCategoriesInitial()) {
    on<GetAllCategories>(_onGetAllCategories);
  }

  final ApiRepository apiRepository;

  Future<void> _onGetAllCategories(
    GetAllCategories event,
    Emitter<AllCategoriesState> emit,
  ) async {
    try {
      emit(const AllCategoriesLoading());

      final categoriesModel = await apiRepository.fetchCategoriesList();

      emit(AllCategoriesLoaded(categoriesModel));

      if (categoriesModel.error != null) {
        emit(AllCategoriesError(categoriesModel.error));
      }
    } catch (e) {
      emit(
        const AllCategoriesError(
          "Failed to fetch all categories data. Is your device online ?",
        ),
      );
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

all_categories_event.dart 的代码

abstract class AllCategoriesEvent extends Equatable {
  AllCategoriesEvent();
}

class GetAllCategories extends AllCategoriesEvent {

  @override
  List<Object> get props => null;

}
Run Code Online (Sandbox Code Playgroud)

all_categories_state.dart 的代码

abstract class AllCategoriesState extends Equatable {
  const AllCategoriesState();
}

class AllCategoriesInitial extends AllCategoriesState {
  AllCategoriesInitial();

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

class AllCategoriesLoading extends AllCategoriesState {
  const AllCategoriesLoading();
  @override
  List<Object> get props => null;
}

class AllCategoriesLoaded extends AllCategoriesState {

  final CategoriesModel categoriesModel;
  const AllCategoriesLoaded(this.categoriesModel);

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

class AllCategoriesError extends AllCategoriesState {

  final String message;
  const AllCategoriesError(this.message);

  @override
  List<Object> get props => [message];
}
Run Code Online (Sandbox Code Playgroud)

它会抛出错误“错误状态:在没有注册事件处理程序的情况下调用 add(GetAllCategories)。请确保通过 on((event, eager) {...}) 注册处理程序”

我家里有这个 add(GetAllCategories) 。dart 文件,但解决方案是编辑此代码,但我无法这样做。有人可以重写最新的块吗?我会很感激。

mko*_*lys 6

让我们逐步了解迁移指南:

  1. package:blocv5.0.0:initialState 已被删除。欲了解更多信息,请查看#1304

您只需AllCategoriesState get initialState => AllCategoriesInitial();从 BLoC 中删除该部分即可。

  1. package:blocv7.2.0 引入新的 on<Event> API。欲了解更多信息,请阅读完整提案

作为此迁移的一部分,该mapEventToState方法被删除,每个事件都使用 API 单独在构造函数中注册on<Event>

首先,在构造函数中注册事件:

AllCategoriesBloc() : super(AllCategoriesInitial()) {
  on<GetAllCategories>(_onGetAllCategories);
}
Run Code Online (Sandbox Code Playgroud)

然后,创建_onGetAllCategories方法:

Future<void> _onGetAllCategories(
  GetAllCategories event,
  Emitter<AllCategoriesState> emit,
) async {
  try {
    emit(const AllCategoriesLoading());

    final categoriesModel = await _apiRepository.fetchCategoriesList();

    emit(AllCategoriesLoaded(categoriesModel));

    if (categoriesModel.error != null) {
      emit(AllCategoriesError(categoriesModel.error));
    }
  } catch (e) {
    emit(
      const AllCategoriesError(
        "Failed to fetch all categories data. Is your device online ?",
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您应该使用发射器,而不是使用Emitter<AllCategoriesState>生成器并产生下一个状态。

这是迁移后的最终结果AllCategoriesBloc

class AllCategoriesBloc extends Bloc<AllCategoriesEvent, AllCategoriesState> {
  AllCategoriesBloc() : super(AllCategoriesInitial()) {
    on<GetAllCategories>(_onGetAllCategories);
  }

  final ApiRepository _apiRepository = ApiRepository();

  Future<void> _onGetAllCategories(
    GetAllCategories event,
    Emitter<AllCategoriesState> emit,
  ) async {
    try {
      emit(const AllCategoriesLoading());

      final categoriesModel = await _apiRepository.fetchCategoriesList();

      emit(AllCategoriesLoaded(categoriesModel));

      if (categoriesModel.error != null) {
        emit(AllCategoriesError(categoriesModel.error));
      }
    } catch (e) {
      emit(
        const AllCategoriesError(
          "Failed to fetch all categories data. Is your device online ?",
        ),
      );
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

额外小费

ApiRepository您可以使用构造函数注入,而不是直接在 BLoC 内部创建实例:

class AllCategoriesBloc extends Bloc<AllCategoriesEvent, AllCategoriesState> {
  AllCategoriesBloc({
    required this.apiRepository,
  }) : super(AllCategoriesInitial()) {
    on<GetAllCategories>(_onGetAllCategories);
  }

  final ApiRepository apiRepository;

  ...
}
Run Code Online (Sandbox Code Playgroud)

现在,在创建 BLoC 时,将存储库的实例传递给构造函数,例如AllCategoriesBloc(apiRepository: ApiRepository()). 这样,您将能够通过模拟依赖项(在本例中为ApiRepository)来正确地对您的 BLoC 进行单元测试。