Spa*_*000 7 dart flutter riverpod
作为序言,我对 Riverpod 完全陌生,所以如果我弄错了一些术语,我深表歉意。
我有一个编辑功能,正在使用 Riverpod 实现,我正在从 flutter_blocs 迁移到该功能。基本上,通过 bloc 实现,我从服务器获取数据,当小部件构建时,将BlocConsumer发出一个事件,将服务器中的数据设置为 bloc 状态,以便我可以在TextInput.
集团实施:
BlocConsumer<JournalBloc, JournalState>(
bloc: BlocProvider.of<JournalBloc>(context)
..add(
SetModelState(
title: journalEntry.title,
rating: journalEntry.rating.toDouble(),
),
),
builder: (context, state) {
return Column(
children: [
TextInput(
labelText: 'label',
value: state.editEntryTitle.value,
onChanged: (title) => context.read<JournalBloc>().add(EditJournalEntryTitleChanged(title: title))
)
],
);
}
Run Code Online (Sandbox Code Playgroud)
现在使用 Riverpod,我遇到的问题是我不知道如何在小部件渲染时将服务器中的值设置为状态。我有我的控制器,我有我的提供者。
我的控制器:
class EditJournalEntryController extends StateNotifier<EditJournalEntryState> {
final JournalService journalService;
EditJournalEntryController({required this.journalService})
: super(EditJournalEntryState());
void setSelectedJournalType(JournalType journalType) {
state = state.copyWith(selectedJournalType: journalType);
}
void setRating(int rating) {
state = state.copyWith(rating: rating);
}
}
final editJournalEntryController =
StateNotifierProvider<EditJournalEntryController, EditJournalEntryState>((ref) {
final journalService = ref.watch(journalServiceProvider);
return EditJournalEntryController(journalService: journalService);
});
Run Code Online (Sandbox Code Playgroud)
我的状态:
class EditJournalEntryState implements Equatable {
final AsyncValue<void> value;
final JournalType? selectedJournalType;
final int? rating;
bool get isLoading => value.isLoading;
EditJournalEntryState({
this.selectedJournalType,
this.rating,
this.value = const AsyncValue.data(null),
});
EditJournalEntryState copyWith({
MealType? selectedJournalType,
int? rating,
AsyncValue? value,
}) {
return EditJournalEntryState(
selectedJournalType: selectedJournalType ?? this.selectedJournalType,
rating: rating ?? this.rating,
value: value ?? this.value,
);
}
@override
List<Object?> get props => [selectedJournalType, rating, value];
@override
bool? get stringify => true;
}
Run Code Online (Sandbox Code Playgroud)
在我的用户界面中,我引用我的控制器,然后使用 mynotifier设置我的状态:
class EditJournal extends StatelessWidget {
const EditFoodJournal({
Key? key,
required this.journalEntry, // coming from server in a few parents above
}) : super(key: key);
final JournalEntry journalEntry;
@override
Widget build(BuildContext context) {
return Consumer(
builder: ((context, ref, child) {
final state = ref.watch(editJournalEntryController);
final notifier = ref.read(editJournalEntryController.notifier);
notifier.setSelectedJournalType(journalEntry.type)
notifier.setRating(journalEntry.rating)
Run Code Online (Sandbox Code Playgroud)
但由于显而易见的原因,我收到此错误:
At least listener of the StateNotifier Instance of 'EditFoodJournalEntryController' threw an exception
when the notifier tried to update its state.
The exceptions thrown are:
Tried to modify a provider while the widget tree was building.
If you are encountering this error, chances are you tried to modify a provider
in a widget life-cycle, such as but not limited to:
- build
- initState
- dispose
- didUpdateWidget
- didChangeDepedencies
Modifying a provider inside those life-cycles is not allowed, as it could
lead to an inconsistent UI state. For example, two widgets could listen to the
same provider, but incorrectly receive different states.
To fix this problem, you have one of two solutions:
- (preferred) Move the logic for modifying your provider outside of a widget
life-cycle. For example, maybe you could update your provider inside a button's
onPressed instead.
- Delay your modification, such as by encasuplating the modification
in a `Future(() {...})`.
This will perform your upddate after the widget tree is done building.
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想从状态而不是我拥有的变量中呈现该值。
我感觉自己撞到了墙。有没有一个理想的方法来处理这个问题?
您正在尝试在构建小部件树时修改提供程序。
final notifier = ref.read(editJournalEntryController.notifier);
notifier.setSelectedJournalType(journalEntry.type)//here
notifier.setRating(journalEntry.rating)//here
Run Code Online (Sandbox Code Playgroud)
这将导致问题,您需要使用初始状态初始化 editJournalEntryController 您可以通过.family 提供程序修饰符来完成
编辑:
像这样的东西
final editJournalEntryController = StateNotifierProvider.family<
EditJournalEntryController,
EditJournalEntryState,
JournalEntry>((ref, journalEntry) {
final journalService = ref.watch(journalServiceProvider);
return EditJournalEntryController(journalService: journalService,journalentry: journalEntry);
});
Run Code Online (Sandbox Code Playgroud)
EditJournalEntryController 将是
class EditJournalEntryController extends StateNotifier<EditJournalEntryState> {
final JournalService journalService;
final JournalEntry journalentry;
EditJournalEntryController({required this.journalService,required this.journalentry})
: super(EditJournalEntryState(selectedJournalType: journalentry.type,rating: journalentry.rating));
void setSelectedJournalType(String journalType) {
state = state.copyWith(selectedJournalType: journalType);
}
void setRating(int rating) {
state = state.copyWith(rating: rating);
}
}
Run Code Online (Sandbox Code Playgroud)
会被称为像
class EditFoodJournal extends StatelessWidget {
const EditFoodJournal({
Key? key,
required this.journalEntry, // coming from server in a few parents above
}) : super(key: key);
final JournalEntry journalEntry;
@override
Widget build(BuildContext context) {
return Consumer(builder: (context, ref, child) {
final state = ref.watch(editJournalEntryController(journalEntry));
return Container();
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4943 次 |
| 最近记录: |