Flutter双视图事件自动同步优化:单数据源与逻辑分离方案咨询
问题描述
我是Flutter新手,正在开发一款个人日程管理应用。应用包含两个视图,分别展示已确认事件和未确认事件。我使用calendar_view库,为两个视图分别实现了自定义Provider(继承自EventController)。
现有代码
自定义Provider代码
class PrivateProvider extends EventController { static final PrivateProvider _instance = PrivateProvider._internal(); factory PrivateProvider() { return _instance; } PrivateProvider._internal() : super(); addEvents(List<Event> events){ super.addAll(events); notifyListeners(); } addEvent(Event event){ super.add(event); notifyListeners(); } }
事件视图Widget代码
@override Widget build(BuildContext context) { var eventsProvider = widget.private ? PrivateProvider() : SharedProvider(); return Scaffold( body: WeekView( controller: eventsProvider, onEventTap: (events, date) => showCustomDialog( context, EventDetail( initialEvent: events.whereType<Event>().toList().first, date: null, confirmed: widget.private)), ), );
当前事件筛选与初始化逻辑
void addEvents(List<Event> events) { List<Event> sharedEvents = events .where((ev) => ev.confirmed == false) .toList(); List<Event> privateEvents = events .where((ev) => ev.confirmed == true) .toList(); PrivateProvider().addEvents(privateEvents); SharedProvider().addEvents(sharedEvents); }
疑问与需求
目前两个事件列表仅通过confirmed布尔值区分,用户修改该状态后,事件需在两个视图间切换。我当前的做法是手动从一个控制器移除事件并添加到另一个控制器,想了解是否能实现自动同步:比如维护单一事件列表,根据confirmed状态自动在两个视图展示。此外,后续计划实现实时更新,希望事件更新时无需在控制器中查找即可自动同步。请问是否有办法分离业务逻辑与视图逻辑?比如通过中央事件Provider实现?我也愿意下载并修改calendar_view的控制器逻辑。
解决方案
1. 实现中央事件Provider
创建全局事件管理类,维护单一数据源,监听事件状态变化并自动同步到视图控制器:
class EventManager extends ChangeNotifier { final List<Event> _allEvents = []; // 两个视图对应的控制器实例 final PrivateProvider _privateProvider = PrivateProvider(); final SharedProvider _sharedProvider = SharedProvider(); List<Event> get allEvents => List.unmodifiable(_allEvents); EventManager() { _syncEventsToControllers(); } void addEvent(Event event) { _allEvents.add(event); event.addListener(_onEventStatusChanged); _syncEventsToControllers(); notifyListeners(); } void addEvents(List<Event> events) { _allEvents.addAll(events); events.forEach((event) => event.addListener(_onEventStatusChanged)); _syncEventsToControllers(); notifyListeners(); } void removeEvent(Event event) { _allEvents.remove(event); event.removeListener(_onEventStatusChanged); _syncEventsToControllers(); notifyListeners(); } // 事件状态变更时自动同步到控制器 void _onEventStatusChanged() { _syncEventsToControllers(); notifyListeners(); } // 按状态筛选事件并同步到对应控制器 void _syncEventsToControllers() { final privateEvents = _allEvents.where((e) => e.confirmed).toList(); final sharedEvents = _allEvents.where((e) => !e.confirmed).toList(); _privateProvider.clear(); _privateProvider.addEvents(privateEvents); _sharedProvider.clear(); _sharedProvider.addEvents(sharedEvents); } // 对外提供控制器访问入口 PrivateProvider get privateProvider => _privateProvider; SharedProvider get sharedProvider => _sharedProvider; }
注意:需要让Event类继承ChangeNotifier,以便状态变化时通知EventManager:
class Event extends ChangeNotifier { bool _confirmed; // 其他事件字段... bool get confirmed => _confirmed; set confirmed(bool value) { if (_confirmed != value) { _confirmed = value; notifyListeners(); // 状态变更触发通知 } } // 构造函数及其他方法... }
2. 修改视图Widget使用中央Provider
在视图中通过EventManager获取对应控制器,替代直接实例化:
@override Widget build(BuildContext context) { final eventManager = Provider.of<EventManager>(context); var eventsProvider = widget.private ? eventManager.privateProvider : eventManager.sharedProvider; return Scaffold( body: WeekView( controller: eventsProvider, onEventTap: (events, date) => showCustomDialog( context, EventDetail( initialEvent: events.whereType<Event>().toList().first, date: null, confirmed: widget.private)), ), ); }
3. 初始化事件时使用中央Provider
替换原有初始化逻辑,直接调用EventManager的添加方法:
// 通过Provider获取EventManager实例 final eventManager = Provider.of<EventManager>(context, listen: false); eventManager.addEvents(yourEventList);
4. (可选)修改calendar_view的EventController支持过滤
如果想进一步简化逻辑,可以修改EventController,让它支持基于条件的事件过滤,无需维护两个独立控制器:
class FilterableEventController extends EventController { final bool Function(Event) filter; FilterableEventController({required this.filter}); // 重写获取事件的方法,只返回符合过滤条件的事件 @override List<Event> getEventsOnDay(DateTime day) { return super.getEventsOnDay(day).where(filter).toList(); } }
然后在EventManager中维护单一数据源,给两个视图提供带不同过滤条件的控制器:
class EventManager extends ChangeNotifier { final FilterableEventController _privateController = FilterableEventController(filter: (e) => e.confirmed); final FilterableEventController _sharedController = FilterableEventController(filter: (e) => !e.confirmed); final List<Event> _allEvents = []; void addEvent(Event event) { _allEvents.add(event); // 事件状态变化时直接通知两个控制器刷新 event.addListener(() { _privateController.notifyListeners(); _sharedController.notifyListeners(); }); _privateController.addEvent(event); _sharedController.addEvent(event); notifyListeners(); } // 其他增删事件方法类似... }
这种方式无需在状态变化时重新同步事件,控制器会自动根据过滤条件返回对应事件。
内容的提问来源于stack exchange,提问作者Serotan
相关产品推荐
相关产品推荐

