如何从实时数据中删除观察者,以便在导航回片段时不会显示两次

Ver*_*era 7 java android android-livedata mediatorlivedata

我有一个片段,当用户成功登录时会显示一个弹出窗口。如果我导航到一个新片段并返回,则会再次显示带有先前用户名的弹出窗口。我使用 SingleLiveEvent 修复了这个问题,但现在必须重构我的代码以使用 MediatorLiveData,因为我的数据可以来自 2 个源(远程和数据库),并且它与 SingleLiveEvent 不兼容。

\n\n

我尝试使用事件包装器并删除 onDestroyView() 上的观察者,但到目前为止没有任何效果,当我移回片段时,livedata onChanged 函数不断被调用。这是我的一些片段:

\n\n
@Override\npublic View onCreateView(LayoutInflater inflater, ViewGroup container,\n                         Bundle savedInstanceState) {\n    // Inflate the layout for this fragment\n    binding = FragmentDashboardBinding.inflate(inflater, container, false);\n    binding.setLifecycleOwner(getActivity());\n\n    //Get the attendanceViewModel for registering attendance\n    attendanceViewModel = ViewModelProviders.of(this).get(AttendanceViewModel.class);\n    attendanceViewModel.getAttendance().observe(getViewLifecycleOwner(), attendanceAndMember -> {\n        if (attendanceAndMember != null && attendanceAndMember instanceof AttendanceMemberModel) {\n            clokedInOutMember = attendanceAndMember.member;\n        }\n        showResultClockInOutPopup();\n    });\n\n    return binding.getRoot();\n}\n\nprivate void showResultClockInOutPopup() {\n\n    clockInBuilder = new AlertDialog.Builder(getActivity());\n\n    View view = getLayoutInflater().inflate(R.layout.status_clock_in_out_popup, null);\n    TextView responseClockInOut = view.findViewById(R.id.responseClockInOut);\n    Button dismissButton = view.findViewById(R.id.dismissButton);\n\n    //Setup Popup Text\n    if (clokedInOutMember != null) {\n        if (StringToBool(clokedInOutMember.is_clocked_in_temp)) {\n            responseClockInOut.setText("Bienvenue " + clokedInOutMember.name + ", tu es bien enregistr\xc3\xa9(e).");\n        } else {\n            responseClockInOut.setText("D\xc3\xa9sol\xc3\xa9 de te voir partir " + clokedInOutMember.name + ", \xc3\xa0 bient\xc3\xb4t!");\n        }\n    } else {\n        responseClockInOut.setText("Oups, il semblerait qu\'il y ait une erreur...\\n Essaye \xc3\xa0 nouveau.");\n    }\n\n    [..SETUP ALERTDIALOG...]\n\n        //Dismiss popup\n        dismissButton.setOnClickListener(v -> {\n            clockInResultDialog.dismiss();\n            clockInResultPopupShowed = false;\n            clokedInOutMember = null;\n        });\n\n        clockInResultDialog.show();\n        clockInResultPopupShowed = true;\n    }\n\n}\n\n@Override\npublic void onDestroyView() {\n    attendanceViewModel.getAttendance().removeObservers(this);\n    super.onDestroyView();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的 ViewModel,我必须使用转换,因为我从片段中获取 userId,传递给 Viewmodel,Viewmodel 将其传递到存储库进行查询(也许有更好的方法?):

\n\n
public class AttendanceViewModel extends AndroidViewModel {\n\nprivate AttendanceRepository repository = AttendanceRepository.getInstance();\npublic LiveData<AttendanceMemberModel> mAttendanceAndMember;\nprivate MutableLiveData<String> mId =  new MutableLiveData<>();\n\nprivate MediatorLiveData<AttendanceMemberModel> mObservableAttendance = new MediatorLiveData<AttendanceMemberModel>();\n{\n    mObservableAttendance.setValue(null);\n\n    mAttendanceAndMember = Transformations.switchMap(mId, id -> {\n        return repository.saveAttendance(id);\n    });\n\n    mObservableAttendance.addSource(mAttendanceAndMember, mObservableAttendance::setValue);\n}\n\n\npublic AttendanceViewModel(@NonNull Application application) {\n    super(application);\n}\n\npublic LiveData<AttendanceMemberModel> getAttendance() {\n    return mObservableAttendance;\n\n}\n\npublic void setMemberId(String id) {\n    mId.setValue(id);\n}\n\n\n@Override\nprotected void onCleared() {\n    mObservableAttendance.setValue(null);\n    super.onCleared();\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Bek*_*Bek 2

我可以建议你两种方法。首先创建一个boolean变量是否显示对话框,Fragment并在显示对话框之后将其设置为true,并在显示对话框之前检查是否显示对话框。第二种方法是在显示对话框之后将livedata值设置为 null 并在显示对话框之前检查观察者值是否为 null。我更喜欢第二种方式。


归档时间:

查看次数:

8167 次

最近记录:

4 年,7 月 前