iDe*_*ode 1 flutter riverpod flutter-riverpod
下面的代码接受用户输入,并在延迟 1 秒后以大写形式打印它。
最小可重现代码:
class FooPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final asyncValue = ref.watch(resultProvider);
print('loading: ${asyncValue.isLoading}');
return Scaffold(
body: Column(
children: [
TextField(onChanged: (s) => ref.read(queryProvider.notifier).state = s),
asyncValue.when(
data: Text.new,
error: (e, s) => Text('Error = $e'),
loading: () => Text('Loading...'),
),
],
),
);
}
}
final stringProvider = FutureProvider.family<String, String>((ref, query) async {
await Future.delayed(Duration(seconds: 1));
return query.toUpperCase();
});
final queryProvider = StateProvider<String>((ref) => '');
final resultProvider = FutureProvider<String>((ref) async {
final query = ref.watch(queryProvider);
return ref.watch(stringProvider(query).future);
});
Run Code Online (Sandbox Code Playgroud)
运行代码后,
a)并等待输出(大写)b),然后等待输出(大写)b),现在控制台将打印loading: true,因此加载小部件会在几分之一秒内构建。这会导致用户体验非常差。最新版本出现此问题2.0.2。那么,如何获取先前的值,以便data在获取数据后能够一致地显示?
更新:
这就是我使用 git 的方式:
dependencies:
flutter:
sdk: flutter
flutter_riverpod:
git:
url: https://github.com/rrousselGit/riverpod/tree/master/packages/flutter_riverpod
ref: master
Run Code Online (Sandbox Code Playgroud)
2.1.0 版本包含额外的实用程序,用于在加载过程中获取先前的值/错误。
注意在发布时,2.1.0 目前尚未发布。如果你想使用它,你可以在 pubspec 中使用 git 依赖项来执行以下操作:
# Using dependency_overrides is necessary due to flutter_riverpod depending on riverpod
dependency_overrides:
flutter_riverpod:
git:
url: https://github.com/rrousselGit/riverpod/
ref: master
path: packages/flutter_riverpod
riverpod:
git:
url: https://github.com/rrousselGit/riverpod/
ref: master
path: packages/riverpod
Run Code Online (Sandbox Code Playgroud)
现在可以在加载状态期间获取先前的值/错误。
假设您定义 aFutureProvider如下:
final counterProvider = StateProvider<int>((ref) => 0);
final futureProvider = FutureProvider<String>((ref) async {
await Future.delayed(Duration(seconds: 2));
return "Hello world ${ref.watch(counterProivder)}';
});
Run Code Online (Sandbox Code Playgroud)
其中更改counterProvider会导致futureProvider返回到加载状态。
使用此代码片段,在 2.1.0 及更高版本中,如果futureProvider返回加载,您仍然可以访问value/ error:
AsyncValue<String> state = ref.watch(futureProvider);
if (state.isLoading) {
// during loading state, value/errors are still available
print(state.value);
print(state.error);
}
Run Code Online (Sandbox Code Playgroud)
当然,if (state.isLoading)相对于漂亮的语法来说,写起来有点不方便when。
默认情况下,when语法已经正确调用data/error而不是loading提供程序因Ref.refresh/而重建Ref.invalidate。
另一方面,如果重建是有意触发的Ref.watch(因为您的提供程序的参数已更改),则不会这样做。
但when公开标志来改变这一点。
更具体地说,你可以写:
AsyncValue<String> state = ref.watch(futureProvider);
state.when(
skipLoadingOnReload: true,
loading: () => print('loading'),
data: (value) => print('value: $value'),
error: (err, stack) => print('error: $err');
);
Run Code Online (Sandbox Code Playgroud)
使用此代码,无论提供程序通过Ref.watch或重建Ref.refresh,该when方法都将跳过loading并调用data/ error。
| 归档时间: |
|
| 查看次数: |
2735 次 |
| 最近记录: |