我正在开发一个在提供程序/管理器中定义了数据源的应用程序。此类(我们称其为InfoProvider
)几乎只是一个黑匣子-它具有一些属性,并在执行时调用这些属性,从而导致这些属性发生更改(类似于Repository的工作方式,但不再调用返回值,它们将执行异步调用,从而导致提供程序的一个或多个属性发生更改。
此设置专用于低功耗蓝牙-我们都知道它在Android上的管理有多么糟糕,我想使其尽可能地异步,并使用databinding + 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样式的.observe(() -> {})
,.subscribe(() -> {})
等类型的交换。可以做到这一点(即如果我将infoProvider.batteryPercent
的值分配给VM的batteryPercentage
字段,它也将接收更新),还是应该直接绑定到infoProvider?
答案 0 :(得分:0)
不调用"pass around" the LiveData field
便无法进入batteryPercent.observe(...)
。此外,您将需要使用Lifecycler 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中处置订阅。
请注意,所有这些都是伪代码,应该比这更清洁。