flutter Riverpod:如何在AsyncNotifier构造函数中获取ref

omqzjyyz  于 2022-12-27  发布在  Flutter
关注(0)|答案(1)|浏览(188)

[Api存储库]

final apiRepository = Provider((ref) {
  Dio dio = ref.watch(appDioProvider);
  return ApiRepository(dio: dio);
});

class ApiRepository {
  final Dio dio;

  ApiRepository({required this.dio});

  late RestClient restClient = RestClient(dio);

  Future<ApiResult> fetchUsers({
    required int page,
    int perPage = 3,
  }) async {
    try {
      Pagination<UserModel> users = await restClient.getUsers(page: page, perPage: perPage);
      return ApiResult.success(users);
    } catch (error, stackTrace) {
      return ApiResult.failure(ApiError.getApiError(error), stackTrace);
    }
  }

  Future<ApiResult> fetchResources({
    required int page,
    int perPage = 3,
  }) async {
    try {
      Pagination<ResourceModel> resources = await restClient.getResources(page: page, perPage: perPage);
      return ApiResult.success(resources);
    } catch (error, stackTrace) {
      return ApiResult.failure(ApiError.getApiError(error), stackTrace);
    }
  }
}

[分页通知器]

class PaginationNotifier<T> extends AsyncNotifier<Pagination<T>> {
  final Future<ApiResult<Pagination<T>>> Function(int) fetchNewData;

  PaginationNotifier({required this.fetchNewData});

  @override
  FutureOr<Pagination<T>> build() {
    state = AsyncLoading<Pagination<T>>();
    return fetchData().then((_) => state.value ?? const Pagination());
  }

  Future<void> fetchData({bool loadMore = false}) async {
    ApiResult<Pagination<T>> newData = await fetchNewData((state.value?.page ?? 0) + 1);

    newData.when(
      success: (value) {
        state = AsyncData<Pagination<T>>(
          value.copyWith(data: [if (loadMore) ...state.value?.data ?? [], ...value.data]),
        );
      },
      failure: (error, stackTrace) {
        state = AsyncError<Pagination<T>>(error, stackTrace).copyWithPrevious(state);
      },
    );
  }

  void loadMore() {
    if (state == AsyncLoading<Pagination<T>>().copyWithPrevious(state)) {
      return;
    }
    state == AsyncLoading<Pagination<T>>().copyWithPrevious(state);
    fetchData(loadMore: true);
  }
}

[用户通知程序]

final userProvider = AsyncNotifierProvider<UserNotifier, Pagination<UserModel>>(() {
  return UserNotifier();
});

class UserNotifier extends PaginationNotifier<UserModel> {
  UserNotifier() : super(
    fetchNewData: ref.watch(apiRepository).fetchUsers // The instance member 'ref' can't be accessed in an initializer error
  );
}

[资源通告程序]

final resourceProvider = AsyncNotifierProvider<ResourceNotifier, Pagination<ResourceModel>>(() {
  return ResourceNotifier();
});

class ResourceNotifier extends PaginationNotifier<ResourceModel> {
  ResourceNotifier() : super(
    fetchNewData: ref.watch(apiRepository).fetchResources // The instance member 'ref' can't be accessed in an initializer error
  );
}

我正在尝试使用Retrofit + Riverpod生成分页API调用。定义了一个调用API的存储库,并将其作为提供程序导入。
PaginationNotifier被创建为可重用的,Repository的函数被设计为在构造函数中接收。
在UserNotifier中,需要ref对象来获取Repository,但不能访问构造函数中的ref对象。
有什么好办法吗?

agxfikkp

agxfikkp1#

你不需要在constructor中获取ref,只需要将你的类修改为:

class PaginationNotifier<T> extends AsyncNotifier<Pagination<T>> {
  late final Future<ApiResult<Pagination<T>>> Function(int) fetchNewData;

  PaginationNotifier() {
    fetchNewData = ref.read(apiRepository).fetchUsers;
  }
  // ...
}

class UserNotifier extends PaginationNotifier<UserModel> {
  // No need of a constructor. 
}

相关问题