在我的应用中,我使用riverpod和flutter_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;
});
,但是即使使用相同的itemId多次调用FutureProvider,也只能第一次大声读取。
其次,我在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");
},
),
],
);
}
}
答案 0 :(得分:0)
使用提供程序的美丽之处之一是它们很有效,因为它们只会计算一次值,除非某些更改会改变该值。
在第一个示例中看到该行为的原因:
,但是即使使用相同的itemId多次调用FutureProvider,也只能第一次大声读取。
是由于我上面提到的提供者的属性。如果您将autoDispose decorator添加到futureProvider,我相信这会解决您的问题。
此外,在第二个示例中始终大声读取它的原因是,即使发生任何视觉上的变化,只要发生任何更改,build方法中的所有内容都将始终重新生成。这可以追溯到我关于提供者有效的第一点,因为除非您明确希望该行为,否则不必重新评估提供的值。