1

私のアプリでは、riverpodflutter_ttsパッケージを使用して http 応答を読み上げています。まず、次のように FutureProvider でデータをフェッチした後に追加しました。

final futureProvider = FutureProvider.family<String, String>((ref, itemId) async {
  // fetch data from server
  final result = await Future.delayed(Duration(seconds: 1)).then((value) => "$itemId");
  await SpeakResult(result); // speak here
  return result;
});

ただし、FutureProvider が同じ itemId で複数回呼び出された場合でも、初めて読み上げられました。

次に、buildメソッドに追加しましたが、ウィジェットを再構築するときに常に読み上げられました。

useProvider(futureProvider("item id")).when(
  loading: () => CircularProgressIndicator(),
  error: (error, stackTrace) => Text("$error"),
  data: (value) async {
    await SpeakResult(value);
    return Text("$value");
  },
);

これを解決するアイデアはありますか?

完全なコードは次のとおりです。


final futureProvider = FutureProvider.autoDispose.family<String, String>((ref, id) async {
  ref.onDispose(() => print("disposed"));
  // fetch data from server
  final result = Future.delayed(Duration(seconds: 1)).then((value) => "$id");
  // await SpeakResult(result);
  return result;
});

final asyncListProvider = StateNotifierProvider((_) => AsyncList());

class AsyncList extends StateNotifier<List<AutoDisposeFutureProvider<String>>> {
  AsyncList() : super([]);

  void add(String id) {
    /*
      //I want to do something like this:
      final asyncValue = futureProvider(id).whenData((value) async {
        await SpeakResult(result);
        return value;
      });
    */
    final asyncValue = futureProvider(id);
    state = [asyncValue, ...state];
  }
}

class MyHomePage extends HookWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final list = useProvider(asyncListProvider.state);
    return ListView(
      children: [
        RaisedButton(
          child: Text("Add data"),
          onPressed: () {
            context.read(asyncListProvider).add("item id");
          },
        ),
        for (final item in list)
          useProvider(item).when(
            loading: () => ListTile(
              title: Center(child: CircularProgressIndicator()),
            ),
            error: (error, stackTrace) => Text("$error"),
            data: (value) {
              // await SpeakResult(value);
              return Text("$value");
            },
          ),
      ],
    );
  }
}
4

1 に答える 1