Flutter 集团:屈服状态不会触发小部件重建
Flutter bloc: yielding state doesn't triggers widget rebuild
在我的提醒应用程序中,当我点击添加提醒按钮时,它实际上将提醒添加到数据库中,然后更新我的提醒,但提醒列表没有重建。出于某种原因,当我删除提醒时,类似的场景效果很好。
我集团的一部分:
void _loadReminders() async {
final reminders = await _repository.getAllReminders();
reminders.sort((a, b) => a.dateTime.isAfter(b.dateTime) ? 1 : -1);
if (reminders.isNotEmpty) {
add(RemindersLoaded(reminders: reminders));
}
}
@override
Stream<MainState> mapEventToState(MainEvent event) async* {
if (event is ItemSelected) {
yield state.copyWith(isSelectedModeActive: true);
} else if (event is SelectModeDisabled) {
yield state.copyWith(isSelectedModeActive: false);
} else if (event is RemindersLoaded) {
yield state.copyWith(reminders: event.reminders);
} else if (event is SaveReminderPressed) {
await _saveReminder(event.reminder);
_loadReminders();
} else if (event is DeletePressed) {
await deleteReminders();
_loadReminders();
add(SelectModeDisabled());
}
}
小部件:
Widget _remindersList(BuildContext context) =>
BlocBuilder<MainBloc, MainState>(
builder: (context, state) {
return ListView.builder(
itemCount: state.reminders.length,
itemBuilder: (context, index) {
return ReminderItem(reminders: state.reminders, index: index);
},
);
},
);
状态:
class MainState extends Equatable {
final bool isSelectedModeActive;
final List<Reminder> reminders;
final int quantityOfSelectedItems;
MainState({
this.isSelectedModeActive = false,
this.reminders,
}) : quantityOfSelectedItems =
reminders.where((reminder) => reminder.isSelected).length;
MainState copyWith({
bool isSelectedModeActive,
List<Reminder> reminders,
}) =>
MainState(
isSelectedModeActive: isSelectedModeActive ?? this.isSelectedModeActive,
reminders: List<Reminder>()..addAll(reminders ?? this.reminders),
);
@override
List<Object> get props => [
isSelectedModeActive,
reminders,
quantityOfSelectedItems,
];
}
浪费了几天时间,试图解决这个问题。有关详细信息,您可以在 github 上查看我的项目:https://github.com/rockstar4095/reminder_flutter_app/tree/main_screen
问题出在 reminder_item.dart 文件中,在函数 _reminderDescription 中,您正在使用 Flexible
和非 Flex 父项。只需删除 Flexible Widget 或使其成为 Row 或 Column Widget 的直接子项,一切都会正常工作。
Widget _reminderDescription(BuildContext context) => Align(
alignment: Alignment.centerLeft,
child: RichText(
overflow: TextOverflow.ellipsis,
text: TextSpan(
text: _current.description,
style: Theme.of(context).textTheme.caption,
),
),
);
同时更新 MainScreen Widget
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final content = Scaffold(
appBar: AppBar(
title: Text('Напоминания'),
actions: [
_deleteIcon(context),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
EditReminderDialog.open(context);
},
child: Icon(Icons.add),
),
body: _remindersList(context),
);
return BlocProvider(
create: (context) {
return context.read<MainBloc>();
},
child: Builder(builder: (context) {
return content;
}),
);
}
编辑
您的弹出对话框保存功能也缺少 Navigator.of(context).pop()
。
Widget _save(BuildContext context) => RaisedButton(
child: Text('Сохранить'),
onPressed: () {
final reminder = Reminder(
id: null,
title: 'test reminder title',
description:
'test reminder description ${DateTime.now().toLocal()}',
dateTime: DateTime.now(),
);
context.read<MainBloc>().add(SaveReminderPressed(reminder: reminder));
Navigator.of(context).pop();
},
);
在我的提醒应用程序中,当我点击添加提醒按钮时,它实际上将提醒添加到数据库中,然后更新我的提醒,但提醒列表没有重建。出于某种原因,当我删除提醒时,类似的场景效果很好。
我集团的一部分:
void _loadReminders() async {
final reminders = await _repository.getAllReminders();
reminders.sort((a, b) => a.dateTime.isAfter(b.dateTime) ? 1 : -1);
if (reminders.isNotEmpty) {
add(RemindersLoaded(reminders: reminders));
}
}
@override
Stream<MainState> mapEventToState(MainEvent event) async* {
if (event is ItemSelected) {
yield state.copyWith(isSelectedModeActive: true);
} else if (event is SelectModeDisabled) {
yield state.copyWith(isSelectedModeActive: false);
} else if (event is RemindersLoaded) {
yield state.copyWith(reminders: event.reminders);
} else if (event is SaveReminderPressed) {
await _saveReminder(event.reminder);
_loadReminders();
} else if (event is DeletePressed) {
await deleteReminders();
_loadReminders();
add(SelectModeDisabled());
}
}
小部件:
Widget _remindersList(BuildContext context) =>
BlocBuilder<MainBloc, MainState>(
builder: (context, state) {
return ListView.builder(
itemCount: state.reminders.length,
itemBuilder: (context, index) {
return ReminderItem(reminders: state.reminders, index: index);
},
);
},
);
状态:
class MainState extends Equatable {
final bool isSelectedModeActive;
final List<Reminder> reminders;
final int quantityOfSelectedItems;
MainState({
this.isSelectedModeActive = false,
this.reminders,
}) : quantityOfSelectedItems =
reminders.where((reminder) => reminder.isSelected).length;
MainState copyWith({
bool isSelectedModeActive,
List<Reminder> reminders,
}) =>
MainState(
isSelectedModeActive: isSelectedModeActive ?? this.isSelectedModeActive,
reminders: List<Reminder>()..addAll(reminders ?? this.reminders),
);
@override
List<Object> get props => [
isSelectedModeActive,
reminders,
quantityOfSelectedItems,
];
}
浪费了几天时间,试图解决这个问题。有关详细信息,您可以在 github 上查看我的项目:https://github.com/rockstar4095/reminder_flutter_app/tree/main_screen
问题出在 reminder_item.dart 文件中,在函数 _reminderDescription 中,您正在使用 Flexible
和非 Flex 父项。只需删除 Flexible Widget 或使其成为 Row 或 Column Widget 的直接子项,一切都会正常工作。
Widget _reminderDescription(BuildContext context) => Align( alignment: Alignment.centerLeft, child: RichText( overflow: TextOverflow.ellipsis, text: TextSpan( text: _current.description, style: Theme.of(context).textTheme.caption, ), ), );
同时更新 MainScreen Widget
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final content = Scaffold(
appBar: AppBar(
title: Text('Напоминания'),
actions: [
_deleteIcon(context),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
EditReminderDialog.open(context);
},
child: Icon(Icons.add),
),
body: _remindersList(context),
);
return BlocProvider(
create: (context) {
return context.read<MainBloc>();
},
child: Builder(builder: (context) {
return content;
}),
);
}
编辑
您的弹出对话框保存功能也缺少 Navigator.of(context).pop()
。
Widget _save(BuildContext context) => RaisedButton(
child: Text('Сохранить'),
onPressed: () {
final reminder = Reminder(
id: null,
title: 'test reminder title',
description:
'test reminder description ${DateTime.now().toLocal()}',
dateTime: DateTime.now(),
);
context.read<MainBloc>().add(SaveReminderPressed(reminder: reminder));
Navigator.of(context).pop();
},
);