我有一个片段,当用户成功登录时会显示一个弹出窗口。如果我导航到一个新片段并返回,则会再次显示带有先前用户名的弹出窗口。我使用 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 …Run Code Online (Sandbox Code Playgroud) 我是 LiveData 的新手,最近一直在做一些测试。我有一个应用程序,我需要在其中显示可以过滤的数据(名称、类别、日期...)。过滤器也可以组合(名称+日期)。该数据来自使用 Retrofit + RXJava 进行的 API 调用。
我知道我可以直接在视图中获取数据,而无需使用 LiveData。但是,我认为使用 ViewModel + LiveData 会很有趣。首先,测试它的工作原理,同时避免在视图不活动时尝试设置数据(感谢 LiveData),并在配置更改时保存数据(感谢 ViewModel)。这些都是我以前必须手动处理的事情。
所以问题是我没有找到一种方法来轻松地使用 LiveData 处理过滤器。如果用户选择一个过滤器,我设法使其与 switchMap 一起使用:
return Transformations.switchMap(filter,
filter -> LiveDataReactiveStreams.fromPublisher(
repository.getData(filter).toFlowable(BackpressureStrategy.BUFFER)));
Run Code Online (Sandbox Code Playgroud)
如果他选择两个过滤器,我发现我可以使用自定义 MediatorLiveData,这就是我所做的。然而,这里的问题是我的存储库调用的次数与我拥有的过滤器的数量一样多,并且我无法同时设置两个过滤器。
我的自定义 MediatorLiveData:
class CustomLiveData extends MediatorLiveData<Filter> {
CustomLiveData(LiveData<String> name, LiveData<String> category) {
addSource(name, name -> {
setValue(new Filter(name, category.getValue()));
});
addSource(category, category -> {
setValue(new Filter(name.getValue(), newCategory));
});
}
}
Run Code Online (Sandbox Code Playgroud)
CustomLiveData trigger = new CustomLiveData(name, category);
return Transformations.switchMap(trigger,
filter -> LiveDataReactiveStreams.fromPublisher(
repository.getData(filter.getName(), filter.getCategory())
.toFlowable(BackpressureStrategy.BUFFER)));
Run Code Online (Sandbox Code Playgroud)
我是否充分理解 MediatorLiveData …
最近我一直在学习 LiveData 上的转换方法
我知道我们可以使用maporswitchMap方法来转换实时数据。假设我们有类似下面的 Player 数据类
data class Player(val name: String, val score: Int = 0)
Run Code Online (Sandbox Code Playgroud)
我们使用map方法将player livedata转换为playerName livedata
val player: LiveData<Player> = ...
val playerName: LiveData<String> =
Transformations.map(player) { it.name }
Run Code Online (Sandbox Code Playgroud)
我的问题是,在观察者函数中执行它有什么区别,因为它们都在主线程中运行?我的意思是,如果我们想获取playerName,那么我们也可以在观察者函数中获取它。为什么我们声明第二个 LiveData 实例来获取它
我从本指南中获取了示例代码:https://proandroiddev.com/livedata-transformations-4f120ac046fc
kotlin android-livedata mutablelivedata mediatorlivedata android-livedata-transformations
更推荐哪种方法来组合多个 LiveData:使用MediatorLiveData或switchMap?
// MediatorLiveData approach
fun <A, B, C> combine(
liveData1: LiveData<A>,
liveData2: LiveData<B>,
onChanged: (A?, B?) -> C
): MediatorLiveData<C> {
return MediatorLiveData<C>().apply {
addSource(liveData1) {
value = onChanged(liveData1.value, liveData2.value)
}
addSource(liveData2) {
value = onChanged(liveData1.value, liveData2.value)
}
}
}
// switchMap approach
fun <A, B, C> combine(
liveData1: LiveData<A>,
liveData2: LiveData<B>,
onChanged: (A, B) -> C
): LiveData<C> {
return liveData1.switchMap { a ->
liveData2.map { b ->
onChanged(a, b)
}
}
}
Run Code Online (Sandbox Code Playgroud)
该 …