阅读文档后,它没有很好地解释什么是ref.read()
、ref.watch()
、 和ref.listen()
。
我的问题如下:
我需要从 Firebase Cloud Firestore 获取 1 个字段 1 次。如何通过 Widget 构建之外的提供者来实现此目的?
以下是我的组合提供商。appStartupProvider
是一个 FutureProvider,我想bool
从 firestore 中的这个 1 字段中获取值。但是,状态中的等待appStartupProvider
“'await'应用于'AsyncValue',这不是'Future'”。
final accountStreamProvider = StreamProvider<Account>((ref) {
final database = ref.watch(databaseProvider);
return database != null ? database.accountStream() : const Stream.empty();
});
final _accountSetupCompleteProvider = Provider<AsyncValue<bool>>((ref) {
return ref
.watch(accountStreamProvider)
.whenData((account) => account?.accountSetupComplete ?? false);
});
final appStartupProvider = FutureProvider<bool>((ref) async {
final accountSetupComplete = await ref.watch(_accountSetupCompleteProvider);
return accountSetupComplete;
});
Run Code Online (Sandbox Code Playgroud)
显然,这里缺少一些有关组合提供程序和 AsyncValue 的关键知识,但我正在尝试实现RiverPod 组合提供程序页面上所述的情况,我在其中看到正在使用等待。
我被小部件测试困住了,我可以使用一些帮助
来重现该行为,请运行下面的代码示例
import \'package:flutter/material.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'home_page.dart\';\n\nvoid main() => runApp(\n const ProviderScope(\n child: MaterialApp(\n home: Material(\n child: MyHomePage(),\n ),\n ),\n ),\n );\n
Run Code Online (Sandbox Code Playgroud)\nimport \'dart:math\';\nimport \'package:flutter/material.dart\';\nimport \'package:flutter_hooks/flutter_hooks.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\n\nextension RoundX on double {\n double roundToPrecision(int n) {\n final f = pow(10, n);\n return (this * f).round() / f;\n }\n}\n\nfinal tasksPod = Provider<List<Future<void> Function()>>(\n (ref) => [\n for (var i = 0; i < 10; ++i)\n () async {\n await Future.delayed(kThemeAnimationDuration);\n }\n ],\n);\n\nfinal progressPod = Provider.autoDispose<ValueNotifier<double>>((ref) {\n final notifier = ValueNotifier<double>(0);\n …
Run Code Online (Sandbox Code Playgroud) 我非常熟悉Provider包并将其与ChangeNotifier
.
假设我有 3 个 getter 和具有不同功能的方法:
import 'package:flutter/foundation.dart';
class GlobalChangeNotifier extends ChangeNotifier {
bool _isLoading = false;
bool _isImageLoading = false;
bool _isObsecurePassword = false;
bool get isLoading => _isLoading;
bool get isImageLoading => _isImageLoading;
bool get isObsecurePassword => _isObsecurePassword;
void setLoading(bool value) {
_isLoading = value;
notifyListeners();
}
void setImageLoading(bool value) {
_isImageLoading = value;
notifyListeners();
}
void setObsecurePassword(bool value) {
_isObsecurePassword = !value;
notifyListeners();
}
}
final globalChangeNotifier …
Run Code Online (Sandbox Code Playgroud) 我是 Riverpod 的新手,尝试在我的 Flutter 应用程序中使用 Riverpod 实现拉动刷新,但似乎在网上找不到任何好的教程。有没有人在使用 Riverpod 时在 Flutter 应用程序中实现了拉动刷新功能。我到处寻找教程,但我发现的大多数都是应用程序加载时的简单网络请求。提前致谢!
将这些依赖项用于 Riverpod 和网络请求。flutter_riverpod:^0.12.1 dio:^3.0.10
我正在浏览 Flutter Riverpod包文档,由于某种原因,“入门”中的基本示例抛出错误:
未定义类“WidgetRef”。尝试将名称更改为现有类的名称,或创建一个名为“WidgetRef”的类。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final helloWorldProvider = Provider((_) => 'Hello World');
void main() {
runApp(
ProviderScope(child: MyApp()),
);
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final String value = ref.watch(helloWorldProvider);
return MaterialApp(
home: Scaffold(
body: Center(
child: Text(value),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
pubspec.yaml
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_riverpod: ^0.14.0+3
dev_dependencies:
flutter_test:
sdk: flutter
Run Code Online (Sandbox Code Playgroud) 目前,我正在刷新一个 FutureProvider,它负责从 Firebase 获取数据并将其显示在带有Liquid_pull_to_refresh包的简单 ListView 中,这会导致列表消失,加载指示器再次显示,最后列表再次显示。
我想要实现的是保持列表显示,并且仅在获取完成后更新它。我正在使用 Riverpod 进行状态管理。
提供者:
final userProfileProvider = FutureProvider.family<FullUserModel?, String?>((ref, value) => ref.read(databaseServiceProvider).getFullUserModel(value));
Run Code Online (Sandbox Code Playgroud)
刷新部分:
LiquidPullToRefresh(
onRefresh: () async {
ref.refresh(userProfileProvider(uid));
},
child: ListView()
)
Run Code Online (Sandbox Code Playgroud)
对此有什么好的方法吗?
如何将 FirebaseAuth 用户传递给 Riverpod 中的 StreamProvider?
使用旧的提供程序包时,我曾经从 FirebaseAuth 获取 user.uid 并将变量传递给 StreamProvider,如果可以获得 user.uid,则返回 StreamProvider。
@override
Widget build(BuildContext context) {
final FirebaseAuthService authService =
Provider.of<FirebaseAuthService>(context, listen: false);
return StreamBuilder<User>(
stream: authService.onAuthStateChanged,
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
final User loggedInUser = snapshot.data;
if (loggedInUser != null) {
final String userId = loggedInUser.userId;
return MultiProvider(
providers: <SingleChildWidget>[
StreamProvider<User>(
initialData: User.initialData(),
create: (_) => DB.instance.getLoggedInUserStream(
loggedInUserId: userId,
),
Run Code Online (Sandbox Code Playgroud) 我是 Flutter 新手,我想升级我的代码。我有一个使用多个文本表单字段的表单,我想使用提供程序和 Riverpod 转换此代码以提高可读性,但我不确定如何执行此操作。\n对于该示例,我将代码简化为只有一个距离字段,但有很多距离字段其他的。
\n这是我的计算器屏幕:
\nimport 'dart:async' show Future;\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter/material.dart';\nimport 'package:app/core/models/model_form_calculator.dart';\nimport 'package:app/core/services/service_form_validator.dart';\nimport 'package:app/core/utils/utils_app_color.dart';\n\nclass CalculatorScreen extends StatefulWidget\n{\n CalculatorScreen({Key key}) : super(key: key);\n\n @override\n _CalculatorScreenState createState() => _CalculatorScreenState();\n}\n\nclass _CalculatorScreenState extends State<CalculatorScreen>\n{\n final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();\n final _formKey = GlobalKey<FormState>();\n\n FormCalculatorModel _formData = FormCalculatorModel();\n bool _autoValidateForm = false;\n\n final TextEditingController _controllerDistance = TextEditingController();\n\n @override\n void initState() {\n super.initState();\n }\n\n @override\n void dispose()\n {\n _controllerDistance.dispose();\n super.dispose();\n }\n\n @override\n Widget build(BuildContext context)\n {\n return GestureDetector(\n onTap: (() => …
Run Code Online (Sandbox Code Playgroud) 在我的示例项目中,我使用riverpod
包和freezed
. 在下面的代码中,我可以成功从服务器获取数据,但是当我尝试使用时model.fromJson
出现此错误:
getting type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
Run Code Online (Sandbox Code Playgroud)
服务器响应数据:
getting type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
Run Code Online (Sandbox Code Playgroud)
login
模型来转换服务器响应的数据和结构:
{
"message": "test message",
"statusCode": 1
}
Run Code Online (Sandbox Code Playgroud)
在LoginResponse
类中,我定义了两个参数message
,statusCode
它们由服务器返回。当我尝试使用此请求时,例如:
LoginModel loginModelFromJson(Map<String, dynamic> str) => LoginModel.fromJson(str);
String loginModelToJson(LoginModel data) => json.encode(data.toJson());
@freezed
class LoginModel with _$LoginModel {
const factory LoginModel({
required LoginResponse response,
}) = _LoginModel;
factory …
Run Code Online (Sandbox Code Playgroud)