Android 观察者没有观察
Android observer is not observing
所以,我在 Android 开发和 observables 方面还很陌生。所以我想要实现的是,在蓝牙扫描仪的每个扫描滴答声中, scanResult
都会被检查,如果它不在列表中,观察到的列表 scanned
会得到更新,如果这个是有效的并且做了一些事情。
我的问题是 observe 函数只运行一次就再也不会运行了
2021-03-05 22:18:54.522 32057-32057/? D/devices: Got something []
2021-03-05 22:18:54.522 32057-32057/? D/devices: Start scan
2021-03-05 22:18:55.209 32057-32057/? D/devices: Checking Had128_1_1 in scanned
2021-03-05 22:18:55.212 32057-32057/? D/devices: adding Had128_1_1 in scanned
据我理解这应该如何工作,他应该在这里 _scanned.value?.add(scanResult.device)
更新并且观察者应该认识到这一点或者我错了吗?
id 可能是 lifecycleOwner 的问题吗?
它来自 MainActivity 到具有 val lifecycleOwner = LocalLifecycleOwner.current
的可组合项
是的,该函数在我的可组合项中被调用(正如我所说,如果我按下按钮,我可以在“Got Something []”上看到它第一次运行)
private val _scanned: MutableLiveData<MutableList<BluetoothDevice>> =
MutableLiveData(mutableListOf())
private val scanned: LiveData<MutableList<BluetoothDevice>> get() = _scanned
private val lockScanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
result?.let { scanResult ->
if (fakeWhitelist.contains(scanResult.device.name)) {
Log.d("devices", "Checking ${scanResult.device.name} in scanned")
val search =
_scanned.value?.find { device -> device.name == scanResult.device.name }
if (search == null) {
Log.d("devices", "adding ${scanResult.device.name} in scanned")
_scanned.value?.add(scanResult.device)
}
}
}
}
}
fun listenForDevices(viewLiveCycleOwner: LifecycleOwner) {
scanned.observe(viewLiveCycleOwner, Observer { deviceList ->
Log.d("devices", "Got something $deviceList")
locationList.value.forEach { locationScaffold ->
val boxNames = locationScaffold.parcelBox.map { it.boxName }
val device = deviceList.last()
Log.d("devices", "$boxNames")
if (!boxNames.contains(device.name)) {
Log.d("devices", "Getting location for ${device.name}")
getLocation(device.name)
}
}
})
startScan()
}
你在这里的错误是你从来没有改变 LiveData
的值。 LiveData
的值可以使用 LiveData.getValue()
检索,并且只能使用 LiveData.setValue()
设置,如果你查看你的实现,你不会在任何地方使用 set 方法。
这是一个相当普遍的误解,认为更改对象的状态会对其引用做一些事情,或者以某种方式通知 class 持有对它的引用,但事实并非如此。如果您考虑 LiveData
的简化版本,您可以将其分解为具有以下核心功能:
- 有当前值
- 持有潜在观察员名单
- 值更改时通知所述观察者
它能够通知观察者的唯一方法是公开一个 method/function,它不仅设置值,而且在必要时通知所有观察者更改。
所以在您的实现中,您检索了当前值并更改了它的状态,但实际上从未将新值设置为 LiveData
。
所以不用
liveData.value?.add(newItem)
我们需要做类似的事情
val list = liveData.value
list?.add(newItem)
_mutableLiveData.value = list
所以,我在 Android 开发和 observables 方面还很陌生。所以我想要实现的是,在蓝牙扫描仪的每个扫描滴答声中, scanResult
都会被检查,如果它不在列表中,观察到的列表 scanned
会得到更新,如果这个是有效的并且做了一些事情。
我的问题是 observe 函数只运行一次就再也不会运行了
2021-03-05 22:18:54.522 32057-32057/? D/devices: Got something []
2021-03-05 22:18:54.522 32057-32057/? D/devices: Start scan
2021-03-05 22:18:55.209 32057-32057/? D/devices: Checking Had128_1_1 in scanned
2021-03-05 22:18:55.212 32057-32057/? D/devices: adding Had128_1_1 in scanned
据我理解这应该如何工作,他应该在这里 _scanned.value?.add(scanResult.device)
更新并且观察者应该认识到这一点或者我错了吗?
id 可能是 lifecycleOwner 的问题吗?
它来自 MainActivity 到具有 val lifecycleOwner = LocalLifecycleOwner.current
的可组合项
是的,该函数在我的可组合项中被调用(正如我所说,如果我按下按钮,我可以在“Got Something []”上看到它第一次运行)
private val _scanned: MutableLiveData<MutableList<BluetoothDevice>> =
MutableLiveData(mutableListOf())
private val scanned: LiveData<MutableList<BluetoothDevice>> get() = _scanned
private val lockScanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
result?.let { scanResult ->
if (fakeWhitelist.contains(scanResult.device.name)) {
Log.d("devices", "Checking ${scanResult.device.name} in scanned")
val search =
_scanned.value?.find { device -> device.name == scanResult.device.name }
if (search == null) {
Log.d("devices", "adding ${scanResult.device.name} in scanned")
_scanned.value?.add(scanResult.device)
}
}
}
}
}
fun listenForDevices(viewLiveCycleOwner: LifecycleOwner) {
scanned.observe(viewLiveCycleOwner, Observer { deviceList ->
Log.d("devices", "Got something $deviceList")
locationList.value.forEach { locationScaffold ->
val boxNames = locationScaffold.parcelBox.map { it.boxName }
val device = deviceList.last()
Log.d("devices", "$boxNames")
if (!boxNames.contains(device.name)) {
Log.d("devices", "Getting location for ${device.name}")
getLocation(device.name)
}
}
})
startScan()
}
你在这里的错误是你从来没有改变 LiveData
的值。 LiveData
的值可以使用 LiveData.getValue()
检索,并且只能使用 LiveData.setValue()
设置,如果你查看你的实现,你不会在任何地方使用 set 方法。
这是一个相当普遍的误解,认为更改对象的状态会对其引用做一些事情,或者以某种方式通知 class 持有对它的引用,但事实并非如此。如果您考虑 LiveData
的简化版本,您可以将其分解为具有以下核心功能:
- 有当前值
- 持有潜在观察员名单
- 值更改时通知所述观察者
它能够通知观察者的唯一方法是公开一个 method/function,它不仅设置值,而且在必要时通知所有观察者更改。
所以在您的实现中,您检索了当前值并更改了它的状态,但实际上从未将新值设置为 LiveData
。
所以不用
liveData.value?.add(newItem)
我们需要做类似的事情
val list = liveData.value
list?.add(newItem)
_mutableLiveData.value = list