flutter 如何在使用Riverpod获得第一个API调用的响应后进行另一个API调用?

4ioopgfo  于 2023-01-02  发布在  Flutter
关注(0)|答案(1)|浏览(207)

我有两个API,第一个是给drawList,它有List,第二个是给我在第一个API的响应中得到的特定绘制的过滤器。
API 1:<BASE_URL>/绘制/列表
API 2:<BASE_URL>/draws?过滤器[移民项目]=drawList[0]
API 1的响应:

[
  "No Program Specified",
  "Canadian Experience Class",
  "Provincial Nominee Program",
  "Federal Skilled Trades"
]

当我从第一个API得到响应时,我想调用第二个API。
对于drawList API,我使用了FutureProvider;对于drawFilterAPI,我使用了StateNotifierProvider,因为当用户从下拉列表中选择另一个字符串时,我需要调用它。
以下是调用drawFilterAPI的提供程序

final updatedItemListProvider = StateNotifierProvider<UpdatedDropDownItemList,
        AsyncValue<PreviousDrawResponse>>(
    (ref) => UpdatedDropDownItemList(ref.read(apiProvider)));

class UpdatedDropDownItemList
    extends StateNotifier<AsyncValue<PreviousDrawResponse>> {
  UpdatedDropDownItemList(this.service) : super(const AsyncLoading()) {
    callChangeValueAPI(null);
  }

  final ApiService service;

  void callChangeValueAPI(String? newValue) async {
    debugPrint('callChangeValueAPI newValue: $newValue');
    state = const AsyncLoading();
    state = await service.getDrawItemList(newValue);
  }
}

这是我的ApiService。目前,我使用了 “未指定程序” 静态。

Future<AsyncValue<PreviousDrawResponse>> getDrawItemList(
      String? newValue) async {
    String url;
    if (newValue == null) {
      url =
          "$baseUrl/draws?filter[immigration_program]=No program specified";
    } else {
      url =
          "$baseUrl/draws?filter[immigration_program]=$newValue";
    }

    final response = await get(Uri.parse(url));

    PreviousDrawResponse previousDrawResponse =
        PreviousDrawResponse.fromJson(jsonDecode(response.body));

    if (response.statusCode == 200) {
      debugPrint("getDrawItemList response: ${jsonDecode(response.body)}");
      return AsyncData(previousDrawResponse);
    } else {
      // throw Exception('Failed to load data!');
      debugPrint("getDrawItemList Error");
      return AsyncError('Failed to load data!', StackTrace.current);
    }
  }

我也使用了.family修饰符。但是,当我改变下拉值时,它不起作用。
有人帮忙吗?

q0qdq0h2

q0qdq0h21#

使用Riverpod 2.0,这变得简单得多。

@riverpod

Future<List<String>> drawList(DrawListRef ref) {
   final response = await get(Uri.parse(url));
   return parseResponse(response); // implement
}

Future<??> filteredDraws(DrawListRef ref, String? program) {
   program ??= "No program specified";

   final response = await get(Uri.parse(...));
   return parseResponse(response); // implement
}

在小部件中,您可以执行以下操作

class TestWidget extends ConsumerStatefulWidget {
  const TestWidget({super.key});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => _TestWidgetState();
}

class _TestWidgetState extends ConsumerState<TestWidget> {

   String? selectedProgram;
   
  @override
  Widget build(BuildContext context) {
    final drawListFuture = ref.watch(drawListProvider.future);

      return SomeContainer(children: [
          FutureBuilder<List<String>>(
             future: drawListFuture,
             builder: (snapshot, context) => 
                        DisplayProgramsList(
                          snapshot.data,
                          onSelected: (program) => 
                            setState((){
                                selectedProgram = program;
                            }))
          ),
          FilteredDraws(selectedDraw)
    ]);
  }
}

class FilteredDraws extends ConsumerWidget {
  final String? program;
  const FilteredDraws({super.key}, this.program);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final filteredDrawsFuture = ref.watch(filteredDrawsProvider(program).future);

      return SomeContainer(children: [
          FutureBuilder<??>(
             future: filteredDrawsFuture,
             builder: (snapshot, context) => DisplayDraws(snapshot.data)
          ),
          FilteredList(selectedDraw)
    ]);
  }
}

相关问题