Android ViewModel观察时数据丢失问题求助
核心问题
从AddNotificationFragment添加数据到MutableLiveData后,FirstFragment能实时收到更新,但返回FirstFragment时数据莫名消失,日志显示返回时LiveData的列表长度为0。
可能原因及修复方案
1. AddNotificationFragment使用了Fragment级别的ViewModel
如果AddNotificationFragment中获取ViewModel的方式是new ViewModelProvider(this),它操作的是自身Fragment级别的ViewModel实例,而非FirstFragment使用的Activity级别ViewModel。添加的数据仅存在于AddNotificationFragment的ViewModel中,Fragment销毁后数据丢失。
修复:
在AddNotificationFragment中,统一使用Activity级别的ViewModelProvider:
notificationsViewModel = new ViewModelProvider(requireActivity()).get(NotificationsViewModel.class);
2. ViewModel列表更新方式存在隐患
直接修改LiveData持有的原列表对象再重新设置引用,不符合LiveData的最佳实践,可能导致数据感知异常。
修复:
修改ViewModel的增删方法,每次创建新列表实例,确保LiveData能正确感知数据变化:
public void addNotification(NotificationContent notificationContent) { List<NotificationContent> currentList = getNotifications().getValue(); List<NotificationContent> newList = new ArrayList<>(currentList); newList.add(notificationContent); notifications.setValue(newList); } public void removeNotification(NotificationContent notificationContent) { List<NotificationContent> currentList = getNotifications().getValue(); List<NotificationContent> newList = new ArrayList<>(currentList); newList.remove(notificationContent); notifications.setValue(newList); } public void addNotification(int position, NotificationContent notificationContent) { List<NotificationContent> currentList = getNotifications().getValue(); List<NotificationContent> newList = new ArrayList<>(currentList); newList.add(position, notificationContent); notifications.setValue(newList); }
3. 观察者生命周期绑定错误
当前使用requireActivity()作为LifecycleOwner,观察者会在Activity生命周期内一直存在,可能引发重复观察或内存泄漏,也可能导致视图重建时接收异常数据。
修复:
使用Fragment视图生命周期作为观察者的LifecycleOwner:
notifs.observe(getViewLifecycleOwner(), new Observer<List<NotificationContent>>() { @Override public void onChanged(List<NotificationContent> notificationContents) { Log.d("ANDROIDAPP", String.format("onChanged: detected and done, item size %d", notificationContents.size())); adapter.updateNotifications(notificationContents); } });
getViewLifecycleOwner()会绑定Fragment的视图生命周期,视图销毁时自动移除观察者,避免重复注册。
4. Adapter数据更新逻辑冗余
当前updateNotifications方法中this.mNotifications.clear()属于冗余操作,且直接引用ViewModel的列表存在外部修改风险。
修复:
简化Adapter的更新方法,创建列表副本:
public void updateNotifications(List<NotificationContent> newNotifications) { this.mNotifications = new ArrayList<>(newNotifications); this.notifyDataSetChanged(); }
通过创建副本,避免ViewModel中的列表修改直接影响Adapter数据,提高稳定性。
验证步骤
- 确认AddNotificationFragment的ViewModel获取方式与FirstFragment一致;
- 修改ViewModel的列表更新逻辑,使用新列表实例;
- 调整观察者的LifecycleOwner为
getViewLifecycleOwner(); - 重新运行测试,查看返回FirstFragment时的日志,确认onChanged中的列表长度是否正确。
内容的提问来源于stack exchange,提问作者Kim Vallée

