英文:
Android ViewModel deletes all my data when observing
问题
我正在使用Android Studio开发应用程序,并希望在RecyclerView中使用MutableLiveData。问题是,当我向MutableLiveData添加新项时,它会得到更新,然后返回到先前的片段时,项目会出现未知原因被清除。
FirstFragment.java
中 onCreateView
方法的代码部分:
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
notificationsViewModel = new ViewModelProvider(requireActivity()).get(NotificationsViewModel.class);
// 绑定RecyclerView
RecyclerView rvNotification = binding.registeredNotification;
Log.d("NA", "New Adapter");
NotificationAdapter adapter = new NotificationAdapter();
Log.d("NA", "Setting adapter");
rvNotification.setAdapter(adapter);
Log.d("NA", "Setting layout");
rvNotification.setLayoutManager(new LinearLayoutManager(getActivity()));
Log.d("NA", "Getting the MLD");
MutableLiveData<List<NotificationContent>> notifs = notificationsViewModel.getNotifications();
Log.d("NA", "Adding observer");
notifs.observe(requireActivity(), 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);
}
});
return binding.getRoot();
}
ViewModel
实现的代码部分:
public class NotificationsViewModel extends ViewModel {
private final MutableLiveData<List<NotificationContent>> notifications = new MutableLiveData<List<NotificationContent>>();
public MutableLiveData<List<NotificationContent>> getNotifications() {
if (notifications.getValue() == null) {
notifications.setValue(new ArrayList<NotificationContent>());
}
return notifications;
}
public void removeNotification(NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.remove(notificationContent);
notifications.setValue(n);
}
public void addNotification(NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.add(notificationContent);
notifications.setValue(n);
}
public void addNotification(int position, NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.add(position, notificationContent);
notifications.setValue(n);
}
}
最后是 RecyclerView.Adapter
的代码:
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.ViewHolder> {
public class ViewHolder extends RecyclerView.ViewHolder {
// 视图项声明...
public ViewHolder(View itemView) {
super(itemView);
// 检索视图项...
}
}
private List<NotificationContent> mNotifications = new ArrayList<>();
public void updateNotifications(List<NotificationContent> newNotifications) {
Log.d("NA", "Clearing");
this.mNotifications.clear();
Log.d("NA", "Setting");
this.mNotifications = newNotifications;
Log.d("NA", "NotifyChangedDataset");
this.notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 一些代码...
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 一些代码...
}
@Override
public int getItemCount() {
return mNotifications.size();
}
}
从你提供的代码和日志来看,似乎问题出现在 onChanged
方法中,当数据更改时,你清空了 mNotifications
并重新设置它,然后调用 notifyDataSetChanged
,这可能导致数据在返回到先前的片段时丢失。你可以尝试不清空 mNotifications
,而是直接将新的通知列表分配给它,然后调用 notifyDataSetChanged
。这样应该能够保留数据。
英文:
I am developing an app with Android Studio, and I wish to use MutableLiveData alongside with RecyclerView. Problem is, when I add a new item to the MutableLiveData, it gets updated, then going back to the previous fragment, the item gets erased for some unknown reason.
Code in my FirstFragment.java
for the method onCreateView
:
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
notificationsViewModel = new ViewModelProvider(requireActivity()).get(NotificationsViewModel.class);
// Binding recycler views
// Notifications
RecyclerView rvNotification = binding.registeredNotification;
Log.d("NA", "New Adapter");
NotificationAdapter adapter = new NotificationAdapter();
Log.d("NA", "Setting adapter");
rvNotification.setAdapter(adapter);
Log.d("NA", "Setting layout");
rvNotification.setLayoutManager(new LinearLayoutManager(getActivity()));
Log.d("NA", "Getting the MLD");
MutableLiveData<List<NotificationContent>> notifs = notificationsViewModel.getNotifications();
Log.d("NA", "Adding observer");
notifs.observe(requireActivity(), 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);
}
});
return binding.getRoot();
}
Code of the ViewModel
implementation :
public class NotificationsViewModel extends ViewModel {
private final MutableLiveData<List<NotificationContent>> notifications = new MutableLiveData<List<NotificationContent>>();
public MutableLiveData<List<NotificationContent>> getNotifications() {
if (notifications.getValue() == null) {
notifications.setValue(new ArrayList<NotificationContent>());
}
return notifications;
}
public void removeNotification(NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.remove(notificationContent);
notifications.setValue(n);
}
public void addNotification(NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.add(notificationContent);
notifications.setValue(n);
}
public void addNotification(int position, NotificationContent notificationContent) {
List<NotificationContent> n = getNotifications().getValue();
n.add(position, notificationContent);
notifications.setValue(n);
}
}
And finally code of the RecyclerView.Adapter
:
public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.ViewHolder> {
public class ViewHolder extends RecyclerView.ViewHolder {
// View Items declaration...
public ViewHolder(View itemView) {
super(itemView);
// View items retrieval ...
}
}
private List<NotificationContent> mNotifications = new ArrayList<>();
public void updateNotifications(List<NotificationContent> newNotifications) {
Log.d("NA", "Clearing");
this.mNotifications.clear();
Log.d("NA", "Setting");
this.mNotifications = newNotifications;
Log.d("NA", "NotifyChangedDataset");
this.notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// Some code ...
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// Some code ...
}
@Override
public int getItemCount() {
return mNotifications.size();
}
}
To get an idea of the interplay between my fragments here is my nav_graph.xml
graphical representation :
But the problem is that after adding an item through the addNotificationFragment
it ends up emptying, here is the log from the log given in the code :
D/ANDROIDAPP: onViewCreated: addNotification 1
D/ANDROIDAPP: onChanged: detected and done, item size 1
D/NA: Clearing
D/NA: Setting
D/NA: NotifyChangedDataset
D/ANDROIDAPP: onViewCreated: addNotification 2
D/ForceDarkHelper: updateByCheckExcludeList: pkg: com.etilawin.tgvmaxplanner activity: com.etilawin.tgvmaxplanner.MainActivity@df816d4
D/ForceDarkHelper: updateByCheckExcludeList: pkg: com.etilawin.tgvmaxplanner activity: com.etilawin.tgvmaxplanner.MainActivity@df816d4
D/NA: New Adapter
D/NA: Setting adapter
D/NA: Setting layout
D/NA: Item Touche helper
D/NA: Button listener
D/NA: Getting the MLD
D/NA: Adding observer
D/ANDROIDAPP: onChanged: detected and done, item size 0
D/NA: Clearing
D/NA: Setting
D/NA: NotifyChangedDataset
答案1
得分: 0
我不确定为什么,但解决方案在这一行中:
```java
notifs.observe(requireActivity(), new Observer<List<NotificationContent>>() {
...
});
这里的 requireActivity()
是不正确的,应该改成 getViewLifecycleOwner()
。
<details>
<summary>英文:</summary>
I don't know exactly why but the solution resides in this line :
```java
notifs.observe(requireActivity(), new Observer<List<NotificationContent>>() {
...
});
Here requireActivity()
is not correct it should be getViewLifecycleOwner()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论