Я работаю над приложением, в котором источник данных определен в Provider / Manager. Этот класс (назовем его InfoProvider
) в значительной степени является просто черным ящиком - он имеет некоторые свойства и вызывает их при выполнении, что приводит к изменению этих свойств (аналогично тому, как работает репозиторий, но вместо вызовов, возвращающих значения, они выполняют асинхронный вызов, который приведет к изменению одного или нескольких свойств провайдера).
Эта настройка предназначена специально для Bluetooth Low Energy - мы все знаем, насколько плохо он работает на Android, и я хотел сделать его как можно более асинхронным и использовать привязку данных + aliveata + 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
для поля batteryPercentage
виртуальной машины, будет ли оно также получать обновления), или я должен привязаться непосредственно к инфо-провайдеру?