mutableStateOf 不会在 MainActivity 中更新

时间:2021-04-15 08:53:13

标签: android kotlin android-jetpack-compose

我有一个蓝牙 LE 扫描正在运行,它针对特定设备进行过滤。这工作正常,我看到这些设备实际上已添加到我的列表中。 但它不会在我的 MainActivity 上触发任何东西。 这是相关代码的一个片段(它的工作方式类似于来自 BTLE 的普通 scanCallback):

@ExperimentalUnsignedTypes
@ExperimentalCoroutinesApi
class BluetoothController(context: Context): ViewModel() {
    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    private val bluetoothSdk = BluetoothSdk()
    private var lifecycleCoroutineScope: LifecycleCoroutineScope? = null
    private var recentScanJob: Job? = null
    private var binding = BluetoothBinding(context)
    val lockDeviceList: MutableState<MutableList<PSLock>> = mutableStateOf(mutableListOf())

    private val bluetoothAdapter: BluetoothAdapter = if (bluetoothManager.adapter == null) {
        throw Exception("Not supported")
    } else {
        bluetoothManager.adapter as BluetoothAdapter
    }

    val activateBluetooth: Boolean? = try {
        bluetoothAdapter.enable()
    } catch (e: Exception) {
        throw Exception(e.message.toString())
    }
    private val psScanListener = object : PSLockScanListener {
        override fun onDeviceScanned(psLock: PSLock) {
            if (fakeWhitelist.contains(psLock.name)) {
                val search = lockDeviceList.value.find { device -> device.name == psLock.name }
                if (search == null) {
                    Log.d(TAG, "lockCallback: adding $psLock")
                    val list = lockDeviceList.value
                    list.add(psLock)
                    lockDeviceList.value = list
                    Log.d("Bluetooth", "New lockDeviceList: ${lockDeviceList.value}")
                    cancelAllScanning()
                }
            }
        }

        override fun onScanError(exception: Exception) {
            TODO("Not yet implemented")
        }
    }
}

我知道这不是完整的代码,但相信我,扫描有效,这是日志:

2021-04-15 08:46:24.874 2936-2936/com.veloce.bluetoothadministrationtool D/Bluetooth: New lockDeviceList: [PSLock(name=PSLOCK, macAddress=00:49:69:2F:51, rssi=-76, batteryLevel=1, doorState=-115, lockState=2, openingTimeInSeconds=218, firmwareVersion=111), PSLock(name=Chr_1_3, macAddress=C7:82:AB:F7:AE, rssi=-62, batteryLevel=78, doorState=2, lockState=0, openingTimeInSeconds=4, firmwareVersion=10), PSLock(name=Ruv14_1_1, macAddress=E1:C1:D3:70:43, rssi=-61, batteryLevel=79, doorState=2, lockState=0, openingTimeInSeconds=3, firmwareVersion=10), PSLock(name=Had128_2, macAddress=E6:AE:52:2B:73, rssi=-71, batteryLevel=79, doorState=2, lockState=0, openingTimeInSeconds=4, firmwareVersion=10), PSLock(name=Chr_1_2, macAddress=FD:33:AB:B5:68, rssi=-61, batteryLevel=74, doorState=2, lockState=0, openingTimeInSeconds=4, firmwareVersion=10), PSLock(name=Thu9_1_1, macAddress=ED:F3:F4:DA:E0, rssi=-71, batteryLevel=79, doorState=2, lockState=0, openingTimeInSeconds=3, firmwareVersion=10)]

所以数据肯定在这里,但是当我在 bluetooth.lockDeviceList.value 上调用 MainActivity 时,它什么也不做。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val isOn = bluetooth.activateBluetooth

        if (isOn == true) {
            Log.d("MainActivity", "Bluetooth is active")
            getLocationPermission()
            bluetooth.startScan()
            Log.d("MainActivity", "PSLock: ${bluetooth.lockDeviceList.value}")
            setContent {
                BluetoothAdministrationToolTheme {
                    // A surface container using the 'background' color from the theme
                    Surface(color = MaterialTheme.colors.background) {
                        Log.d("Bluetooth", "lockDeviceList: ${bluetooth.lockDeviceList.value}")
                        Column() {
                            Text("Hello")
                            Button(onClick = { bluetooth.startScan() }) {
                                Text("Start")
                            }
                            LazyColumn {
                                itemsIndexed(items = bluetooth.lockDeviceList.value) { _, device ->
                                    Log.d("Bluetooth", "YXC: ${bluetooth.availableLocks.value}")
                                    Column(modifier = Modifier.fillMaxWidth()) {
                                        Card() {
                                            Text(device.name)
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else {
            setContent {
                Greeting(name = "bluetooth not turned on")
            }
        }
    }

我尝试在不同的范围内调用 lockDeviceList,但它在任何地方都不起作用。有谁知道这里有什么问题吗?

2 个答案:

答案 0 :(得分:1)

val list = lockDeviceList.value

您正在获取之前的列表实例并对其进行修改,因此在将其重新设置为状态时,状态会认为未进行任何更改,因为该实例仍然相同。

如果你创建一个新的列表实例状态可以刷新,例如:

val list = mutableListOf().apply { addAll(lockDeviceList.value) }

答案 1 :(得分:-1)

您需要使用参数 MutableState<MutableList<PSLock>>,而不是 MutableList<PSLock> - xxx.value