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