0

I have simple viewpager and toolbar in my code :

@Composable
fun DefaultAppBar(
                  mainViewModel: MainViewModel
) {
    CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl ) {
        TopAppBar(
            backgroundColor = Color.White
            ,
            title = {
                Text(text = "",
                    modifier = Modifier
                        .clickable { }
                        // margin
                        .padding(start = 160.dp)

                )
            },
            actions = {
                if(mainViewModel.searchWidgetVisibility.value) {
                    IconButton(
                        onClick = {  },
                        modifier = Modifier,

                        ) {
                        Icon(
                            imageVector = Icons.Filled.Search,
                            contentDescription = "Search Icon",
                            tint = Color.Black,
                            modifier = Modifier,

                            )
                    }
                }


            }
        )
    }

}

As you can see above, I have an search icon which I want it to be visible whenever I enter SecondScreen in my viewpager .

MainViewModel.kt :


class MainViewModel:ViewModel() {

    private val _searchWidgetVisibility: MutableState<Boolean> = mutableStateOf(value = false)


    val searchWidgetVisibility: MutableState<Boolean> = _searchWidgetVisibility


    fun updateSearchWidgetVisibility(newValue:Boolean) {
        _searchWidgetVisibility.value = newValue
    }
}

The searchWidgetVisibility controls the visibility of my search icon.

These are my pages in my viewpager :


@Composable
fun SecondScreen(
    mainViewModel: MainViewModel
) {
    mainViewModel.updateSearchWidgetVisibility(true)
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(color = C2)
        ,
        contentAlignment = Alignment.Center
    ) {
        Text(text = "second screen")
    }
}

@Composable
fun FirstScreen(
    mainViewModel: MainViewModel
) {
    mainViewModel.updateSearchWidgetVisibility(false)
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(color = C2)
        ,
        contentAlignment = Alignment.Center
    ) {
        Text(text = "first screen")
    }
}

But that does not work. when my search icon become visible for the first time,

when I navigate to the FirstScreen, It does not become invisible.

what is the problem here?

1 Answer 1

1

You need to place your mainViewModel.updateSearchWidgetVisibility(false) to not be called in your composition, Compose code needs to be side effect free. Because Composables can run at any time, in parallel or not at all. The position of where you are running that line of code, is not guaranteed to be executed at all.

More info here: https://developer.android.com/jetpack/compose/mental-model#parallel

If you need those functions to run when that composable is added to the composition, you should use LaunchedEffect to do so.

@Composable
fun FirstScreen(
    mainViewModel: MainViewModel
) {
    LaunchedEffect(mainViewModel) {
        mainViewModel.updateSearchWidgetVisibility(false)
    }
    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(color = C2)
        ,
        contentAlignment = Alignment.Center
    ) {
        Text(text = "first screen")
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.