android - Android LiveData 和提供者/管理器模式
问题描述
我正在开发一个在 Provider/Manager 中定义数据源的应用程序。这个类(我们称之为它InfoProvider
)几乎只是一个黑盒子——它有一些属性,并且在执行时调用这些属性会导致这些属性的更改(类似于 Repository 的工作方式,但它们不是调用返回值,而是执行一个异步调用将导致提供者的一个或多个属性发生变化)。
这个设置是专门针对低功耗蓝牙的——我们都知道它在 Android 上的管理有多糟糕,我想让它尽可能异步,并使用数据绑定+livedata+viewmodels 来实现完全响应的架构。
使用 Xamarin 这很容易,只需将 定义InfoProvider
为 ViewModel 中的字段,并绑定到其字段。但是我不一定要公开所有视图模型中的所有字段(有些可能只需要设备的电池状态,有些可能需要完全访问权限,有些可能只执行功能而不等待响应)。对于函数,很容易代理,但对于LiveData<T>
我没有找到太多信息。我将如何前进并“绕过” LiveData 字段?
例子:
class InfoProvider {
var batteryPercent = MutableLiveData<Int>()
public fun requestBatteryUpdate() {
[...]
batteryPercent.value = newValue
}
}
// ViewModel for accessing device battery, inheriting from architecture ViewModel
class DeviceBatteryViewModel: ViewModel() {
var batteryPercentage = MutableLiveData<Int>()
val infoProvider: InfoProvider by inject()
init {
// TODO: Subscribe this.batteryPercentage to infoProvider.batteryPercent
fun onButtonClick() {
infoProvider.requestBatteryUpdate()
}
}
class DeviceBatteryFragment: Fragment() {
val ViewModel: DeviceBatteryViewModel by inject()
private lateinit var binding: DeviceBatteryBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
DeviceBatteryBinding.inflate(inflater, container, false).also { binding = it }.root
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.viewModel = this.ViewModel
}
}
// res/layout/fragment_devicebattery.xml
<layout [namespaces]>
<data class="bindings.DeviceBatteryBinding>
<variable android:name="viewModel" type=".DeviceBatteryViewModel />
</data>
<WhatEverLayout [...]>
<TextView [...] android:text="@{viewModel.batteryPercentage.toString()}" />
<Button [...] android:onClick="@{() -> viewModel.onButtonClick()}" />
</WhatEverLayout>
</layout>
我想避免的是 Rx-style.observe(() -> {})
等.subscribe(() -> {})
类型的交流。可以这样做(即,如果我将值分配给infoProvider.batteryPercent
VM 的batteryPercentage
字段,它也会接收更新),还是应该直接绑定到 infoProvider?
解决方案
"pass around" the LiveData field
没有调用就没有办法batteryPercent.observe(...)
。此外,您将需要使用 aLifecycler Owner
来观察该字段(除非您ObserveForever
不推荐使用哪个解决方案)。
我的建议是这样的:
InfoProvider {
val repositoryBatteryUpdate = BehaviorSubject.create<Int>()
fun observeRepositoryBatteryUpdate(): Observable<Int> {
return repositoryBatteryUpdate
}
fun requestBatteryUpdate(){
// Pseudo code for actually update
// Result goes into repositoryBatteryUpdate.onNext(...)
}
}
ViewModel{
val status: MutableLiveData<Int>
init{
repository.observeRepositoryItems()
.subscribe( update -> status.postValue(status))
}
fun update(){
repository.requestBatteryUpdate()
}
}
Fragment{
viewModel.status.observe() // <-- Here you observe Updates
viewModel.update()
}
请注意,您必须在 ViewModel onCleared 中处理订阅。
请注意,所有这些都是伪代码,应该比这更干净。
推荐阅读
- c# - C#类继承、接口和实例化
- python - Python Flask API - 发布和接收字节数组和元数据
- apache-kafka - 如何将 Avro 事件推送到 Memsql
- powershell - Terraform GCP:在创建时在 Windows 实例中运行 PowerShell
- sql - 如何选择没有冗余值的 SQL 连接表
- android - 房间得到 ConcurrentModificationException
- git - 更改原点后的 Git 提交分支
- python - 如何在 python 中使用 c++ 库?
- c++ - RestoreFile 调用(文件管理 API - fmapi.dll)返回无效句柄
- c++ - 如何过滤所选目录中的图像文件(在 listWidget 内)