Android 观察者未观察

时间:2021-03-05 21:40:45

标签: android kotlin bluetooth observable

所以,我在 Android 开发方面还是很新的,而且还在研究 observables。所以我想要实现的是,在蓝牙扫描仪的每次扫描滴答上,scanResult 都会被检查,如果它不在列表中,则观察到的列表 scanned 会得到更新,如果是有效的,并做出一些事情。 我的问题是观察函数只运行一次,然后再也不会运行

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 可能是生命周期所有者的问题吗? 它从 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()
    }

1 个答案:

答案 0 :(得分:1)

您的错误在于您从未更改 LiveData 的值。 LiveData 的值可以使用 LiveData.getValue() 检索,并且只能使用 LiveData.setValue() 进行设置,如果您查看一下您的实现,则不会在任何地方使用 set 方法。

认为改变对象的状态会对它的引用做一些事情,或者以某种方式通知持有它的引用的类,这是一个很常见的误解,但事实并非如此。如果您考虑简化版的 LiveData,您可以将其分解为具有以下核心功能:

  • 有当前价值
  • 持有潜在观察员名单
  • 当值改变时通知观察者

它能够通知观察者的唯一方法是公开一个方法/函数,该方法/函数不仅设置值,而且在必要时通知所有观察者更改。


因此,在您的实现中,您检索了当前值并更改了其状态,但实际上从未为 LiveData 设置新值。

所以代替

liveData.value?.add(newItem)

我们需要做类似的事情

val list = liveData.value
list?.add(newItem)
_mutableLiveData.value = list
相关问题