英文:
AsyncNotifier keeps rendering UI when I use it with ref.watch in flutter
问题
在build
方法中,我初始化返回值的AsyncNotifier。
class ContractConfigViewModel extends AsyncNotifier<ContractConfigModel> {
late final AuthenticationRepository _authRepository;
@override
FutureOr<ContractConfigModel> build() async {
_authRepository = ref.read(authRepo);
final userId = _authRepository.user!.uid;
final adminData = await _authRepository.getAdminProfile(userId);
final adminProfile = AdminProfileModel.fromJson(adminData!);
if (!adminProfile.master) {
return ContractConfigModel(
contractType: adminProfile.contractType,
contractName: "${adminProfile.region} ${adminProfile.smallRegion}");
}
return ContractConfigModel(
contractType: adminProfile.contractType,
contractName: adminProfile.region,
);
}
void setContractType(String value) {
state = const AsyncValue.loading();
final contractModel = ContractConfigModel(
contractType: value,
contractName: state.value!.contractName,
);
state = AsyncValue.data(contractModel);
}
void setContractName(String value) {
state = const AsyncValue.loading();
final contractModel = ContractConfigModel(
contractType: state.value!.contractType,
contractName: value,
);
state = AsyncValue.data(contractModel);
}
}
这里的getAdminProfile
函数是用于从Firestore获取数据的函数。
Future<Map<String, dynamic>?> getAdminProfile(String uid) async {
final doc = await _db.collection("admin").doc(uid).get();
return doc.data()!;
}
我需要在UI中使用ContractConfigModel
的值。所以,当我从ConsumerStatefulWidget
返回UI时,我使用ref.watch
函数来更新UI,每当ContractConfigModel
的值被更新时。
@override
Widget build(BuildContext context) {
return ref.watch(contractConfigProvider).when(
data: (data) {
final userContractType = data.contractType;
final userContractName = data.contractName;
print(userContractName);
return FutureBuilder(
// ...
);
},
// ...
);
}
但是,当我打印从ref.watch(contractConfigProvider)
获取的数据时,即使ContractConfigModel
的值没有被更新,它仍然会持续打印值。所以,即使我在这个组件中更新了一些内容,它也会被覆盖。
是什么原因导致contractConfigProvider
持续运行在这里?
请帮助我。
此外,我收到以下错误消息:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following FirebaseException was thrown building DefaultSelectionStyle:
[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
The relevant error-causing widget was:
MaterialApp
MaterialApp:file:///Users/hayat/FlutterProjects/ProjectsFiles/onldocc_admin/lib/main.dart:47:24
main.dart:47
When the exception was thrown, this was the stack:
#1 <anonymous closure> (http://localhost:50230/packages/riverpod/src/stack_trace.dart:9:11)
#2 when (http://localhost:50230/packages/riverpod/src/result.dart:110:17)
#3 get requireState (http://localhost:50230/packages/riverpod/src/framework/element.dart:200:17)
#4 read (http://localhost:50230/packages/riverpod/src/framework/provider_base.dart:106:19)
#5 read (http://localhost:50230/packages/riverpod/src/framework/container.dart:229:20)
#6 read (http://localhost:50230/packages/riverpod/src/framework/element.dart:691:23)
#7 <anonymous closure> (http://localhost:50230/packages/onldocc_admin/router.dart:19:31)
#8 processRedirect (http://localhost:50230/packages/go_router/src/configuration.dart:432:62)
#9 redirect (http://localhost:50230/packages/go_router/src/configuration.dart:444:14)
#10 [_redirect] (http://localhost:50230/packages/go_router/src/parser.dart:149:10)
...
这个错误是因为没有创建Firebase App,需要调用Firebase.initializeApp()
来创建Firebase App。
英文:
I have AsyncNotifier and in build
method, I initialize return value.
class ContractConfigViewModel extends AsyncNotifier<ContractConfigModel> {
late final AuthenticationRepository _authRepository;
@override
FutureOr<ContractConfigModel> build() async {
_authRepository = ref.read(authRepo);
final userId = _authRepository.user!.uid;
final adminData = await _authRepository.getAdminProfile(userId);
final adminProfile = AdminProfileModel.fromJson(adminData!);
if (!adminProfile.master) {
return ContractConfigModel(
contractType: adminProfile.contractType,
contractName: "${adminProfile.region} ${adminProfile.smallRegion}");
}
return ContractConfigModel(
contractType: adminProfile.contractType,
contractName: adminProfile.region,
);
}
void setContractType(String value) {
state = const AsyncValue.loading();
final contractModel = ContractConfigModel(
contractType: value,
contractName: state.value!.contractName,
);
state = AsyncValue.data(contractModel);
}
void setContractName(String value) {
state = const AsyncValue.loading();
final contractModel = ContractConfigModel(
contractType: state.value!.contractType,
contractName: value,
);
state = AsyncValue.data(contractModel);
}
}
final contractConfigProvider =
AsyncNotifierProvider<ContractConfigViewModel, ContractConfigModel>(
() => ContractConfigViewModel(),
);
ContractConfigModel:
class ContractConfigModel {
String contractType;
String contractName;
ContractConfigModel({
required this.contractType,
required this.contractName,
});
ContractConfigModel.empty()
: contractType = "",
contractName = ";";
}
Here, getAdminProfile
function is function to get data from FireStore
.
Future<Map<String, dynamic>?> getAdminProfile(String uid) async {
final doc = await _db.collection("admin").doc(uid).get();
return doc.data()!;
}
And I need values of this ContractConfigModel
in UI.
So when I return UI from ConsumerStatefulWidget
, I use ref.watch function to update UI, whenever this ContractConfigModel value is udpated.
@override
Widget build(BuildContext context) {
return ref.watch(contractConfigProvider).when(
data: (data) {
final userContractType = data.contractType;
final userContractName = data.contractName;
print(userContractName);
return FutureBuilder(
.....
But when I print data coming from ref.watch(contractConfigProvider)
, it keeps printing value permanently even though ContractConfigModel value is not updated.
So even though I update something in this component, It is overwritten.
What causes keeps run contractConfigProvider here?
Please help me..
plus)
I get this error message
═╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following FirebaseException was thrown building DefaultSelectionStyle:
[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
The relevant error-causing widget was:
MaterialApp
MaterialApp:file:///Users/hayat/FlutterProjects/ProjectsFiles/onldocc_admin/lib/main.dart:47:24
main.dart:47
When the exception was thrown, this was the stack:
#1 <anonymous closure> (http://localhost:50230/packages/riverpod/src/stack_trace.dart:9:11)
#2 when (http://localhost:50230/packages/riverpod/src/result.dart:110:17)
#3 get requireState (http://localhost:50230/packages/riverpod/src/framework/element.dart:200:17)
#4 read (http://localhost:50230/packages/riverpod/src/framework/provider_base.dart:106:19)
#5 read (http://localhost:50230/packages/riverpod/src/framework/container.dart:229:20)
#6 read (http://localhost:50230/packages/riverpod/src/framework/element.dart:691:23)
#7 <anonymous closure> (http://localhost:50230/packages/onldocc_admin/router.dart:19:31)
#8 processRedirect (http://localhost:50230/packages/go_router/src/configuration.dart:432:62)
#9 redirect (http://localhost:50230/packages/go_router/src/configuration.dart:444:14)
#10 [_redirect] (http://localhost:50230/packages/go_router/src/parser.dart:149:10)
#11 parseRouteInformationWithDependencies (http://localhost:50230/packages/go_router/src/parser.dart:98:7)
#12 [_processRouteInformation] (http://localhost:50230/packages/flutter/src/widgets/router.dart:730:12)
#13 restoreState (http://localhost:50230/packages/flutter/src/widgets/router.dart:594:7)
#14 [_doRestore] (http://localhost:50230/packages/flutter/src/widgets/restoration.dart:912:5)
#15 didChangeDependencies (http://localhost:50230/packages/flutter/src/widgets/restoration.dart:898:7)
#16 didChangeDependencies (http://localhost:50230/packages/flutter/src/widgets/router.dart:669:11)
#17 [_firstBuild] (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5132:11)
#18 mount (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4957:5)
#19 inflateWidget (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3964:15)
#20 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3695:20)
#21 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#22 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#23 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
#24 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#25 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#26 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#27 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
#28 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#29 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#30 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#31 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
#32 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#33 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#34 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#35 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
#36 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#37 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#38 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#39 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5057:5)
#40 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#41 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#42 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#43 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
#44 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#45 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#46 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#47 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5057:5)
#48 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#49 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#50 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5146:11)
#51 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#52 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5169:5)
#53 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3679:14)
#54 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#55 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#56 update (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5312:5)
....
#693 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#694 [_firstBuild] (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4963:5)
#695 mount (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4957:5)
#696 inflateWidget (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3964:15)
#697 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3701:18)
#698 performRebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:5006:16)
#699 rebuild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4701:7)
#700 [_firstBuild] (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4963:5)
#701 mount (http://localhost:50230/packages/flutter/src/widgets/framework.dart:4957:5)
#702 inflateWidget (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3964:15)
#703 updateChild (http://localhost:50230/packages/flutter/src/widgets/framework.dart:3701:18)
#704 [_rebuild] (http://localhost:50230/packages/flutter/src/widgets/binding.dart:1195:16)
#705 mount (http://localhost:50230/packages/flutter/src/widgets/binding.dart:1164:5)
#706 <anonymous closure> (http://localhost:50230/packages/flutter/src/widgets/binding.dart:1111:16)
#707 buildScope (http://localhost:50230/packages/flutter/src/widgets/framework.dart:2713:19)
#708 attachToRenderTree (http://localhost:50230/packages/flutter/src/widgets/binding.dart:1110:12)
#709 attachRootWidget (http://localhost:50230/packages/flutter/src/widgets/binding.dart:943:24)
#710 <anonymous closure> (http://localhost:50230/packages/flutter/src/widgets/binding.dart:924:7)
#711 internalCallback (http://localhost:50230/dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart:48:19)
════════════════════════════════════════════════════════════════════════════════════════════════════
答案1
得分: 0
尝试将你的 ContractConfigModel
设为不可变 —— 所有字段必须为 final
,构造函数必须为 const
。这样应该能解决你的问题。
另外,考虑使用 freezed 来通过 copyWith
轻松修改你的模型。
英文:
Try making your ContractConfigModel
immutable -- all fields must be final
and the constructor const
. This should solve your issue.
Also, consider using freezed to easily change your model via copyWith
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论