0

I don't understand to force recompose is actually a good idea or not. I cannot find a way to solve the problem. I have value of mutableStateOf it's type of Boolean and I am calling a function onResume to check that Boolean value in my viewmodel.

BloodPressurePairViewModel.kt

class BloodPressurePairViewModel : BaseViewModel() {
   
    var isBluetoothEnabled by mutableStateOf(false)
        private set
   
    fun setBluetoothEnable(newValue: Boolean) {
        isBluetoothEnabled = newValue
    }

    fun handleBluetoothScanState(bluetoothAdapter: BluetoothAdapter) {
        if (isBluetoothEnabled) {
            getPairedDevice(bluetoothAdapter)
            startScan(bluetoothAdapter)
        } else {
            cancelTimeWarning()
            stopScan(bluetoothAdapter)
        }
    }

     fun cancelTimeWarning() {
        // more logic here
    }

    // more function here I am not adding.

}

BluetoothConnectionContentStateful

fun BluetoothConnectionContentStateful(
    context: Context = LocalContext.current,
    viewModel: BloodPressurePairViewModel = getViewModel(),
) {
    val activity = context as ComponentActivity
    val rememberPairScreenState = rememberConnectionScreenState(context, viewModel)

    DisposableEffect(key1 = lifecycleOwner) {
          val lifeCycleEventObserver = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_RESUME -> {
viewModel.handleBluetoothScanState(rememberPairScreenState.bluetoothAdapter)
                            rememberPairScreenState.bluetoothStatusRegister.apply {
                                   context.registerReceiver(this,IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
                        },
                        Lifecycle.Event.ON_PAUSE -> {
                            rememberPairScreenState.unRegisterBluetoothStatusReceiver()
                        }
                        else -> {}
                    }
                }
                lifecycleOwner.lifecycle.addObserver(lifeCycleEventObserver)
                onDispose {
                    lifecycleOwner.lifecycle.removeObserver(lifeCycleEventObserver)
                }
            }

rememberConnectionScreenState

@Composable
fun rememberConnectionScreenState(context: Context, viewModel: BloodPressurePairViewModel) = remember {
    ConnectionScreenState(context, viewModel)
}

class ConnectionScreenState(context: Context, private val viewModel: BloodPressurePairViewModel) {
    private val bluetoothManager: BluetoothManager by lazy { activity.getSystemService(BluetoothManager::class.java) }
    val bluetoothAdapter: BluetoothAdapter by lazy { bluetoothManager.adapter }
    var bluetoothStatusRegister = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                when (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
                    BluetoothAdapter.STATE_OFF -> viewModel.setBluetoothEnable(false)
                    BluetoothAdapter.STATE_ON -> viewModel.setBluetoothEnable(true)
                }
            }
        }
    }

    fun unRegisterBluetoothStatusReceiver() {
        activity.unregisterReceiver(bluetoothStatusRegister)
    }
}

When bluetoothStatusRegister is trigger and BluetoothAdapter.STATE_OFF is true and then I called viewModel.setBluetoothEnable(false) the isBluetoothEnabled is false. Then I don't understand how to recall the function of handleBluetoothScanState(bluetoothAdapter). So is this good idea to recompose the function? Thanks

z.g.y
  • 5,512
  • 4
  • 10
  • 36
Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127
  • I assume you are referring to one of the answers suggesting to use the composer and invoke a recomposition, not sure how the person who answered it uses it, but simply invoking it will throw you an exception, also its hard to compile your code to see what your'e experiencing, same with your other recently posted question. – z.g.y Nov 22 '22 at 11:19
  • @z.y so what is the solution for that? – Kotlin Learner Nov 22 '22 at 11:22
  • ooof!, there you go, you got an answer man. – z.g.y Nov 22 '22 at 11:25

1 Answers1

4

Generally it is not what you want to do. Especially because your recomposition can lead to recompositions of another composables which you don't need. In addition, as z.y. mentioned, this can lead to exception.

What you should do is to tie your recomposition to bluetooth state, which you will save in your ViewModel. Then you can use LaunchedEffect to invoke some actions on state change.

val bluetoothState by remember { mutableStateOf (viewModel.bluetoothState) } 
// Please note that design of type you want your state to be is up to you
LaunchedEffect(bluetoothState) {
    // Perform any manipulation you want on bluetooth state change
}
Steyrix
  • 2,796
  • 1
  • 9
  • 23
  • `remember` can be used in @composable function right? – Kotlin Learner Nov 22 '22 at 11:27
  • @vivekmodi yes, the code I posted belongs to composable function – Steyrix Nov 22 '22 at 11:28
  • one more question @Steyrix should I use `mutableStateOf` or `derivedStateOf` inside `remember` ? – Kotlin Learner Nov 22 '22 at 11:29
  • @vivekmodi I guess, since your bluetooth state is not a product of another state objects, `mutableStateOf` is enough. – Steyrix Nov 22 '22 at 11:31
  • Sorry `bluetoothState` is not a variable in my code. Which one are you pointing about? I am little bit confused.. – Kotlin Learner Nov 22 '22 at 11:34
  • @vivekmodi I suggest you to create such variable in your ViewModel. It can be of Boolean type. Then use it in your composable to update views accordingly to your current bluetooth state. – Steyrix Nov 22 '22 at 11:36
  • Why not use `LaunchedEffect(viewModel.bluetoothState)`? What is the local variable in the composable accomplishing? – Tenfour04 Nov 22 '22 at 12:18
  • @Tenfour04 I missed that :) I ll edit my question later accordingly to your comment – Steyrix Nov 22 '22 at 13:30
  • Ah, OK. And actually in this case, I think creating the new state would have prevented the composable from seeing changes in the view model because it was only getting a snapshot at the time the composable was first called due to the use of `remember`. – Tenfour04 Nov 22 '22 at 14:11
  • I am not sure that I understood you correctly. Isn’t it triggering recompose with the updated value due to the use of mutableState? – Steyrix Nov 22 '22 at 14:16