Когда вы внимательно изучите механизм привязки между TextField и TextEditingController, вы поймете, что между ними существует двусторонняя привязка. Следовательно, любые прямые изменения в TextField будут уведомлять и обновлять его TextEditingController. Аналогично, любые прямые изменения в TextEditingController будут уведомлять и обновлять его TextField.
Теперь попробуем реализовать двусторонний механизм привязки. Рассмотрим следующий пример:
class NotificationValue {
final String subject;
final String message;
const NotificationValue({
required this.subject,
required this.message,
});
NotificationValue copyWith({
String? subject,
String? message,
}) {
return NotificationValue(
subject: subject ?? this.subject,
message: message ?? this.message,
);
}
}
class NotificationController extends ValueNotifier<NotificationValue> {
NotificationController({
String subject = '',
String message = '',
}) : super(NotificationValue(
subject: subject,
message: message,
));
String get subject => value.subject;
String get message => value.message;
set subject(String nextValue) {
value = value.copyWith(
subject: nextValue,
);
}
set message(String nextValue) {
value = value.copyWith(
message: nextValue,
);
}
}
class NotificationInput extends StatefulWidget {
const NotificationInput({
super.key,
required this.controller,
});
final NotificationController controller;
@override
State<NotificationInput> createState() => _NotificationInputState();
}
class _NotificationInputState extends State<NotificationInput> {
final subjectController = TextEditingController();
final messageController = TextEditingController();
@override
void initState() {
subjectController.text = widget.controller.subject;
messageController.text = widget.controller.message;
super.initState();
}
@override
void dispose() {
subjectController.dispose();
messageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(controller: subjectController),
TextField(controller: messageController),
],
);
}
}
Как видите, NotificationController предоставляет уведомления в форме NotificationValue. По сути, он следует шаблону проектирования TextEditingController, который предоставляет уведомления в форме TextEditingValue.
Теперь давайте представим вопрос программирования: как вы можете создать двустороннюю привязку между NotificationInput и NotificationController. Следовательно, любые прямые изменения в NotificationInput будут уведомлять и обновлять его NotificationController. Аналогично, любые прямые изменения в NotificationController будут уведомлять и обновлять его NotificationInput.
ПРЕДУПРЕЖДЕНИЕ: помните, что существует возможность циклической взаимоблокировки (то есть, когда пользовательский интерфейс и контроллер продолжают уведомлять друг друга в бесконечном цикле).
Вы можете использовать прослушиватель с проверкой, если значения не равны для достижения этого. Замените initState следующим кодом
@override
void initState() {
super.initState();
subjectController.text = widget.controller.subject;
messageController.text = widget.controller.message;
subjectController.addListener(() {
if (subjectController.text != widget.controller.subject) {
widget.controller.subject = subjectController.text;
}
});
messageController.addListener(() {
if (messageController.text != widget.controller.message) {
widget.controller.message = messageController.text;
}
});
widget.controller.addListener(() {
if (subjectController.text != widget.controller.subject) {
subjectController.text = widget.controller.subject;
}
if (messageController.text != widget.controller.message) {
messageController.text = widget.controller.message;
}
});
}