在我的 Flutter 项目中,我通常倾向于将 Provider 与 Change Notifier 一起用于依赖注入和状态管理目的,因为我发现它比其他解决方案更直观且更少样板,而且我从来没有遇到过任何问题使用这种方法。但最近,我读了很多有关其他状态管理方法的文章,并且听到很多人说 Change Notifier 基本上是一个糟糕且性能较差的状态管理解决方案,特别是在大型应用程序中。就像我说的,我自己从来没有遇到过 Provider 和 Change Notifier 的任何问题,但我仍然是初级开发人员,所以......无论如何,情况真的是这样吗?如果是这样,那么使用 Provider 和 Change Notifier 到底会出现哪些问题?目前有哪些其他推荐用于 Flutter 的状态管理解决方案?
provider state-management dart flutter flutter-change-notifier
我开始学习 flutter 课程,在状态管理部分我决定学习 Getx 状态管理。无论如何,在这个商店教程中,我试图在按下时更改图标状态,但它没有。
我是新手,所以如果你帮助我,我会很感激。
product_item.dart
import 'package:flutter/material.dart';
import 'package:getx_pattern/app/ui/android/products_overview/widgets/product_details.dart';
import 'package:get/get.dart';
import '../../../theme/app_theme.dart';
import './product.dart';
import './products.dart';
class ProductItem extends StatelessWidget {
final pIndex;
// final String title;
// final String imageUrl;
ProductItem({
this.pIndex,
});
productDetails() {
Get.to(
ProductDetailScreen(),
arguments: product.findById(pIndex.id).title,
transition: Transition.rightToLeft,
);
}
final Products product = Get.put(Products());
// final Product pp = Get.put(Product(
// id: null, title: null, description: null, price: null, imageUrl: null));
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: GetBuilder<Products>( …
Run Code Online (Sandbox Code Playgroud) 是否有与 Riverpod 中 Provider 的 ChangeNotifierProvider 小部件等效的小部件?
用例是仅当父小部件为 ChangeNotifierProvider/或在其小部件树中具有 ChangeNotifierProvider 的页面已使用 推送到导航器堆栈时才创建提供程序create
。我希望在弹出页面时自动处理提供者,并且 ChangeNotifierProvider 小部件从小部件树中删除,就像在 Provider 中一样。
provider state-management flutter flutter-change-notifier riverpod
我遵循了这个 优秀的Riverpod 教程。在最后的步骤中,作者使用了以下代码:
\nfinal _buttonState = Provider<ButtonState>((ref) {\n return ref.watch(timerProvider.state).buttonState;\n});\nfinal buttonProvider = Provider<ButtonState>((ref) {\n return ref.watch(_buttonState);\n});\n
Run Code Online (Sandbox Code Playgroud)\n和
\nfinal _timeLeftProvider = Provider<String>((ref) {\n return ref.watch(timerProvider.state).timeLeft;\n});\nfinal timeLeftProvider = Provider<String>((ref) {\n return ref.watch(_timeLeftProvider);\n});\n
Run Code Online (Sandbox Code Playgroud)\n我尝试使用_buttonState
and _timeLeftProvider
,据我所知,该应用程序运行正常。所以,我的问题是:
buttonProvider
and timeLeftProvider
?非常感谢!
\n2020-10-26 更新(main.dart
代码和输出图像)
我的main.dart
代码是:
import \'package:flutter/material.dart\';\nimport \'package:flutter_hooks/flutter_hooks.dart\';\nimport \'package:hooks_riverpod/hooks_riverpod.dart\';\nimport \'package:riverpod_timer_app/timer.dart\';\n\nfinal timerProvider = StateNotifierProvider<TimerNotifier>(\n (ref) => TimerNotifier(),\n);\n\nfinal _buttonState = Provider<ButtonState>((ref) {\n return ref.watch(timerProvider.state).buttonState;\n});\n\nfinal …
Run Code Online (Sandbox Code Playgroud) 我有一个选择选项菜单。因此,当用户选择一个选项时,我想使用该选项向服务器发送 GET/ 请求,并从服务器接收过滤后的数据。
这可以使用 useEffect(() => {// send the request}, [criteria]) 来实现
因为,useEffect 确保只有在 setCriteria 完成后请求才会发送到服务器。
但是,我正在使用react-query
图书馆。所以说,它是不允许使用useQuery
的内部useEffect
。
结果,请求在 setState 完成之前发送到服务器。这样,服务器将获得先前选择的值,而不是当前选择的值。
更改:
<select
name="filter"
value={criteria}
onChange={async (e) => {
setCriteria(e.target.value);
}}
>
<option>Most recent First</option>
<option>Price: Low to High</option>
<option>Price: High to Low</option>
</select>;
Run Code Online (Sandbox Code Playgroud)
获取帖子:
const FetchPosts = async () => {
const {
data: { posts },
} = await axios.get(`${process.env.API_URL}/api/posts`, {
params: {
filter: criteria,
},
});
return posts;
};
useQuery("posts", FetchPosts);
const …
Run Code Online (Sandbox Code Playgroud) 为什么我们有时使用notifyListeners 以及为什么我们不使用notifyListeners?我们如何在 changenotifier 中使用函数?
例如,在这段代码中,有时我们使用了notifyListeners,但有时我们没有使用notifyListeners(在login() 函数中)。为什么 ?当我们使用notifyListeners 时?
String get userEmail => _userEmail;
set userEmail(String value) {
_userEmail = value;
notifyListeners();
}
String get userPassword => _userPassword;
set userPassword(String value) {
_userPassword = value;
notifyListeners();
}
String get userName => _userName;
set userName(String value) {
_userName = value;
notifyListeners();
}
DateTime get dateOfBirth => _dateOfBirth;
set dateOfBirth(DateTime value) {
_dateOfBirth = value;
notifyListeners();
}
Future<bool> login() async {
try {
isLoading = true;
print(userEmail);
print(userPassword);
if (isLogin) {
await FirebaseAuth.instance.signInWithEmailAndPassword( …
Run Code Online (Sandbox Code Playgroud) 在我的程序中,我有两个不同的 Blocsbloc1
和bloc2
. 我使用MultiBlocProvider
并添加这两个块。现在我想BlocListener
在BlocBuilder
. MultiBlocProvider
因为bloc1
我想要BlocBuilderand
因为bloc2
我想要BlocListener
。我怎样才能做到这一点?
Scaffold(
body: MultiBlocProvider(
providers: [
BlocProvider<GenerateFieldsBloc>(
create: (_) => bloc1,
),
BlocProvider<SubmitFieldBloc>(
create: (_) => bloc2,
),
],
child:() //here how can I use both BlocListener and BlocBuilder ???
),
);
Run Code Online (Sandbox Code Playgroud) 我正在学习在 Flutter 中使用 Getx 库,我遇到了以下问题:想法是有一个 TextFields 列表,其中每个 TextFields 都是可水平扩展的,也就是说,它在屏幕上占用的大小由键入的单词的大小,随着单词大小的增加,TextField 的大小也会增加。如果我添加一行,通过FloatingActionButton,没有问题,我可以顺利打字,但是当我添加第二行时,出现以下错误:
\n\n\n\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90 捕获异常通过小部件库 \xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\ x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\ xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\ x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\ x90\xe2\x95\x90\xe2\x95\x90\n构建 NewLineKeyword(dirty) 时抛出以下断言:\n在构建期间调用 setState() 或 markNeedsBuild()。
\n
\n\n此 GetX 小部件无法标记为需要构建,因为框架已经在构建小部件的过程中。仅当小部件的祖先之一当前正在构建时,才可以将其标记为需要在构建阶段构建。允许此异常,因为框架在子窗口之前构建父窗口小部件,这意味着将始终构建脏后代。否则,框架可能不会在此构建阶段访问此小部件。\n调用 setState() 或 markNeedsBuild() 的小部件是:GetX<NewLineKeywordController>
\n
\n\n控制器: null\ntag: null\nhas builder\nstate: GetXState#ae1d4(controller: Instance of \'NewLineKeywordController\')\n当进行有问题的调用时当前正在构建的小部件是: NewLineKeyword\ndirty\n相关错误-导致小部件是\nNewLineKeyword
\n
下图显示了运行时的情况:
\n\n下面是可水平扩展的 TextField 的代码:
\nclass NewLineKeyword extends GetView<NewLineKeywordController>{\n final Key myKey;\n\n const NewLineKeyword({ \n Key? key, \n required this.myKey, \n }) : super(key: key);\n\n @override\n Widget build(BuildContext context) …
Run Code Online (Sandbox Code Playgroud) 最近我发现我们可以使用以下任一方法访问提供者值
Consumer<Model>(build: (context, value, child){
return Widget(child: value.valueName),
},
)
Run Code Online (Sandbox Code Playgroud)
或者使用
context.watch<Model>().valueName
最佳实践是什么?
我看过很多赞扬 Bloc State 管理的教程,它有什么特别之处,我应该作为初学者学习它吗?如果没有,是否有任何初学者友好的状态管理技术?
作为初学者,我如何选择在flutter中使用哪种状态管理?我先学哪一个?主要考虑因素和权衡是什么?
我正在使用 GetX。
\n当我从 EventScreen 转到主屏幕 -> 一切正常...然后返回 EventScreen 并返回主屏幕(使用左侧的抽屉菜单)...第二次返回主屏幕时,会发生此错误:
\n[GETX] Instance "EventsScreenController" has been initialized\n[GETX] GOING TO ROUTE /HomeScreen\n[GETX] Instance "HomeScreenController" has been created\n[GETX] Instance "HomeScreenController" has been initialized\n[GETX] GOING TO ROUTE /EventsScreen\n[GETX] GOING TO ROUTE /HomeScreen\n[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: setState() or markNeedsBuild() called during build.\nThis Obx widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build …
Run Code Online (Sandbox Code Playgroud) state-management ×12
flutter ×11
dart ×7
flutter-getx ×3
provider ×3
bloc ×2
riverpod ×2
caching ×1
flutter-bloc ×1
javascript ×1
react-query ×1
reactjs ×1
setstate ×1