6

I do have a mutableStateof in my HiltViewModel named loading. I am updating the value of loading from a function in the view model which is being passed to @composable function and being used there. The case is that the loading value is updating perfectly in the viewModel but not reflecting in the @Composable function. My viewModel is:

@HiltViewModel class AuthenticationViewModel @Inject constructor( private val repository: AppRepository, application: Application ): ViewModel() { val loading = mutableStateOf(false) fun update() = viewModelScope.launch { loading.value = true } } 

loading value is updated here but not reflecting in the @composable

@Composable fun LoginScreen( viewModel: AuthenticationViewModel, actions: MainActions ) { val loading = viewModel.loading.value //Loading is another composable function where bool value is passed Loading(state = loading) CustomNavigationButton(title = "Sign In",enabled = true,onClick = {viewModel.update()}) } 

Now when I click on the navigation button the view model function is being called and the loading state is also being updated but not reflected back in the @Composable

Loading Composable is:

@Composable fun Loading(state:Boolean) { var showDialog by remember { mutableStateOf(state) } if(showDialog){ Dialog(onDismissRequest = { showDialog = false }, DialogProperties( dismissOnBackPress = false,dismissOnClickOutside = false )) { Box( modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)), contentAlignment= Alignment.Center, ){ CircularProgressIndicator() } } } } 
4
  • Try replacing val loading = viewModel.loading.value with val loading = viewModel.loading and Loading(state = loading) with Loading(state = loading.value) Commented Nov 18, 2021 at 17:37
  • Nope getting the same result Commented Nov 18, 2021 at 17:40
  • Add your Loading composable in the question. Commented Nov 18, 2021 at 17:46
  • added the loading composable Commented Nov 18, 2021 at 17:49

2 Answers 2

3

The Issue is in the Loader composable function. if condition was always set to false as the mutable state was never updating in that specific composable function. Replaced:

@Composable fun Loading(state:Boolean) { var showDialog by remember { mutableStateOf(state) } if(showDialog){ Dialog(onDismissRequest = { showDialog = false }, DialogProperties( dismissOnBackPress = false,dismissOnClickOutside = false )) { Box( modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)), contentAlignment= Alignment.Center, ){ CircularProgressIndicator() } } } } 

with

@Composable fun Loading(state:Boolean) { if(state){ Dialog(onDismissRequest = {}, DialogProperties( dismissOnBackPress = false,dismissOnClickOutside = false )) { Box( modifier = Modifier.size(100.dp).background(Color.White, shape = RoundedCornerShape(8.dp)), contentAlignment= Alignment.Center, ){ CircularProgressIndicator() } } } } 
Sign up to request clarification or add additional context in comments.

Comments

0

The thing to see is that state isn't really state; its just a value. You turn it into state by wrapping it in mutableStateOf. Any changes to state (the value), will trigger a recomposition of @Composable Loading which is what you want. But because you told Compose to "remember" the state, it says "ok something triggered a recompositon, here's this MutableState that I was remembering for you."

The way to fix this is to tell Compose when to forget (i.e. invalidate) and remember something new. You can do that by setting a key on remember. If you know how keys work in side effects then this should be familiar:

var showDialog by remember(key1 = state) { mutableStateOf(state) } 

While you're at it, you might as well refactor names to make it more clear:

@Composable fun Loading(showDialog : Boolean) { var showDialogInternal by remember(key1 = showDialog) { mutableStateOf(showDialog) } ... } 

Holding reference to a remembered showDialogInternal is really only helpful since you are also updating that state inside Loading. If not then you don't need state at all and you should take @Ankit Shah 's answer, although it's not clear how you'd actually dismiss the dialog

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.