2

How to start executing a block of code after changing the value of MutableLiveData when using .observeAsState()?

Example: MutableLiveData changes and after need to call Toast.

This code returns error «Composable calls are not allowed inside the calculation parameter of inline fun remember(calculation: () -> TypeVariable(T)): TypeVariable(T)»

@Composable
fun TextInfo() {
    val isSuccess by remember { viewModel.isSuccess.observeAsState() }//var isSuccess = MutableLiveData<Boolean>() — in ViewModel

    LaunchedEffect(isSuccess) {
        Log.d("IS SUCCESS", "trues")
    }
}
z.g.y
  • 5,512
  • 4
  • 10
  • 36
TriangleN
  • 167
  • 1
  • 1
  • 7

2 Answers2

1

The block inside remember{…} is not a composable scope, its a similar issue you'll have when your try to put a @Composable function inside a lambda block or another function which is not a composable.

I also don't think you need remember{…} here anymore, since its already handled by your ViewModel

val isSuccess by viewModel.isSuccess.observeAsState()

LaunchedEffect(isSuccess) {
     if (isSuccess) {
         Log.d("IS SUCCESS", "trues")
     }     
}

I made some attempt on your code, changing it like this,

val isSuccess by viewModel.isSuccess.observeAsState()

Button(onClick = { viewModel.updateSuccess() }) {}
            
LaunchedEffect(isSuccess) {
    if (isSuccess) {
        Log.e("IS_SUCCESS", "IS_SUCCESS? $isSuccess")
    }
    
}

and in your ViewModel

fun updateSuccess() {
   isSuccess.value = isSuccess.value?.not()
}

everytime the button is clicked, it prints

29568-29568 E/IS_SUCCESS: IS_SUCCESS? true
29568-29568 E/IS_SUCCESS: IS_SUCCESS? true
z.g.y
  • 5,512
  • 4
  • 10
  • 36
  • Log is called without pressing the button – TriangleN Dec 01 '22 at 12:46
  • 1
    its expected, since its part of the first comopisition, dont be mistaken with the key like you do with an if-else, the key doesnt evaluate coniditions, LaunchedEffect will trigger once and will trigger again if the key you supplied to it, changes, if the key doesnt change the LaunchedEffect will not re-execute – z.g.y Dec 01 '22 at 13:21
  • 1
    @TriangleN edited my answer to make sure the Log statements will only print when `isSuccess` is `true` – z.g.y Dec 01 '22 at 15:46
0

You can create a Toast inside LaunchedEffect even though not available in question i assume you try to call LocalContext.current inside LaunchedEffect which is not allowed because LocalContext.current requires calls from Composable scope.

What are differents between Composable function and normal function in Android?

@Composable
fun TextInfo() {
    val isSuccess by remember { viewModel.isSuccess.observeAsState() }//var isSuccess = MutableLiveData<Boolean>() — in ViewModel
    val context = LocalContext.current

    LaunchedEffect(isSuccess) {
        if(isSuccess){
            Toast.makeText(context, "IS SUCCESS", "trues", Toast.LENGTH_SHORT).show()
        }
    }
}
Thracian
  • 43,021
  • 16
  • 133
  • 222