StateNotifierPovider我一直在试图找出观察对象与观察它所暴露的通知程序之间的区别。正如我们在文档中看到的,当状态更改时,观察通知程序对象不会触发对象的构建方法。经过实验,看起来观察提供者对象就像会暴露通知程序中的状态一样ref.read(provider.notifier).state。我无法真正理解直接监视提供程序与监视提供程序之间的区别provider.notifier以及为什么它在监视通知程序并更改其状态时不触发构建方法。
我想知道 getx 和 Riverpod 有什么区别。我很困惑我将在实际项目中使用这两种状态管理工具中的哪一种。
我一直在阅读 Go Router 与 Riverpod 的最新实现,但不知道如何使用 Firebase 身份验证流,而且我不知道是否需要使用刷新监听。
https://github.com/lucavenir/go_router_riverpod/tree/master/complete_example
firebase firebase-authentication flutter flutter-riverpod flutter-go-router
为了访问非小部件类内的提供程序,我使用了 Reader 函数。将 Riverpod 依赖更新到 ^2.0.2 版本后,Reader 功能似乎不再可用。您建议采取什么解决方法?
我可以将 Ref 或 WidgetRef 作为参数传递给类构造函数吗?
当我传递 WidgetRef 时,它无法识别状态和方法。
这是我的Notifier:
class Counter extends Notifier<int> {
final int initial;
Counter(this.initial);
@override
int build() => initial;
}
Run Code Online (Sandbox Code Playgroud)
我需要initial向它传递值,但我无法再使用family修饰符来做到这一点。
// Error
final counterProvider = NotifierProvider.family<Counter, int, int>((initial) {
// How to get the initial value to pass here?
return Counter(initial);
});
Run Code Online (Sandbox Code Playgroud) 我和家人有这个提供者
final gameControllerProvider = ChangeNotifierProvider.autoDispose
.family<GameController, GameLevel>((ref, gameLevel) {
final gameController = GameController()..initializeController(gameLevel, ref);
return gameController;
});
Run Code Online (Sandbox Code Playgroud)
要观察这一点,我们必须在提供者中传递一个参数,如下所示:
final controller = ref.watch(gameControllerProvider(gameLevel));
Run Code Online (Sandbox Code Playgroud)
现在,如果我们必须听这个提供者的话,我们必须做这样的事情
ref.listen<GameController>(gameControllerProvider(gameLevel), ((previous, next) {
....
}));
Run Code Online (Sandbox Code Playgroud)
现在,我认为每次我们在提供程序中传递一个参数时,它都会创建另一个对象实例。问题是我的控制器和 ref.listen(provider) 是否指向同一个实例?或不?
我正在使用 go_router 和 Riverpod 开发 Flutter 应用程序,分别用于导航和状态管理。该应用程序有一个小部件,可以显示实时摄像头源,我想“关闭它”并在其他页面堆叠在其顶部时释放摄像头。
这是没有这样逻辑的GoRouter 代码示例。
GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => CameraWidget(),
routes: [
GoRoute(
path: 'page1',
builder: (context, state) => Page1Screen(),
),
],
),
],
)
Run Code Online (Sandbox Code Playgroud)
我的第一次尝试是在 GoRoute 构建器中添加一些逻辑:
GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) {
if (state.location == "/") {
return CameraWidget();
}
return Center(child: Text("Camera not visible");
},
routes: [
GoRoute(
path: 'page1',
builder: (context, state) => Page1Screen(),
),
],
),
],
)
Run Code Online (Sandbox Code Playgroud)
但这显然不起作用 …
我查看了 Riverpod 的反例,发现它使用 ConsumerWidget 而不是 ConsumerStatefulWidget。
如果ConsumerWidget可以显示状态变化,还有必要使用ConsumerStatefulWidget吗?为什么 Riverpod 作为状态管理解决方案同时具有有状态和无状态消费者小部件?好像还有什么我还没明白的事
如何像inStateNotifier一样使用加载/错误状态?FutureProviderRiverpod
我们可以使用 setState、带三元运算符的 var isLoading 和 didChangeDependency 对 Provider 执行相同的操作。
我刚开始使用 RiverPod。之前我使用 Provider 进行状态管理。
如果是提供程序,我可以使用小部件树之外的提供程序来使用语法获取值
Provider.of<MyModel>(context,listen:true).someFunction();
Run Code Online (Sandbox Code Playgroud)
我如何在 RiverPod 中做同样的事情?现在我正在使用 Consumer Builder 和 Consumer Widget。我想知道是否有一种方法可以在不使用 Consumer 的情况下调用 Riverpod 提供商。
当小部件位于同一文件中时,我能够在小部件之间共享数据,但是当小部件位于不同文件中时,用户界面不会重建,而且我似乎没有得到正确的结果。
请检查下面的代码,看看我的不足之处。(我添加了图像以便于阅读和文本代码以便于 CTRL C - CTRL V)
但它不会通知其他小部件/重建当点击第 45 行的按钮时,第 44 行的文本成功更改,但第 26 行的屏幕没有更改
//-------------navigation_provider.dart----------------//
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class NavigationProvider extends ChangeNotifier{
bool showUserProfile = true;
void toggleProfile(toggle){
showUserProfile = toggle;
notifyListeners();
}
}
Run Code Online (Sandbox Code Playgroud)
//--------------desktop_scaffold.dart----------------//
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:premiumpeaches/providers/navigation_provider.dart';
import 'package:flutter/material.dart';
final navigatorProvider = ChangeNotifierProvider((ref) => NavigationProvider());
class DesktopScaffold extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return SizedBox(
child: ref.watch(navigatorProvider).showUserProfile == true ? UserProfileComponent() : ProfileSettingsComponent()
)
}
Run Code Online (Sandbox Code Playgroud)
//--------------user_profile_component.dart----------------// …
这是我的用例:
数据已下载
final dataProvider = FutureProvider<MyModel>((ref) async {
return fetchData();
});
Run Code Online (Sandbox Code Playgroud)
它在小部件的构建方法中像这样使用:
ref.watch(dataProvider).when(
data: DataWidget(data),
error: ErrorWidget(),
loading: LoadingWidget())
Run Code Online (Sandbox Code Playgroud)
用户可以选择刷新数据:
ref.refresh(dataProvider.future);
Run Code Online (Sandbox Code Playgroud)
但是,当出现错误时(例如手机处于飞行模式),会提供错误,因此 DataWidget 会丢失并替换为 ErrorWidget...有没有办法使用 Riverpod 来提供/保留现有数据而不是错误?我相信这是常见的情况,但我没有找到解决这个问题的任何优雅的解决方案。我也阅读了文档,但没有找到与此相关的任何有用信息。我错过了什么吗?(我是 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 { …Run Code Online (Sandbox Code Playgroud) flutter ×13
flutter-riverpod ×13
riverpod ×10
dart ×3
firebase ×1
flutter-getx ×1
gorouter ×1
routemaster ×1
state ×1