Home > Back-end >  LaunchedEffect(Unit) doesn't trigger if app is reopened
LaunchedEffect(Unit) doesn't trigger if app is reopened

Time:01-21

If my app has never refreshed some user details before upon launch, I want it to do so.

I tried putting the call to refresh in a LaunchedEffect(Unit). Now let's say the request fails. I can have a snackbar with a retry button, but what about when the user presses the back button and the app is reopened? No recomp seems to occur to automatically try again, so is the only option in this case to tie the logic to the lifecycle of the app, something like this answer? It seems very counterintuitive to Compose, and a very common use case to refresh data when an app is resumed from the background.

    when (uiState) {
        HomeUiState.RequiresInitializing -> {
            LaunchedEffect(Unit) {
                refresh()
            }
            Box(
                modifier = modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                LoadingWheel()
            }
        }
    }

CodePudding user response:

If I understand what you are trying to achieve correctly, once an app/screen is "resumed" you want to refresh some data?

You can create something like this :

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Lifecycle.State.RESUMED
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.CoroutineScope


@Composable
fun RepeatOnLifecycleEffect(
    state: Lifecycle.State = RESUMED,
    action: suspend CoroutineScope.() -> Unit
) {
    val lifecycle = LocalLifecycleOwner.current

    LaunchedEffect(key1 = Unit) {
        lifecycle.repeatOnLifecycle(state, block = action)
    }
}

This will perform an "action" each time the lifecycle is resumed, or choose another lifecycle state ...

For your use case maybe :

@Composable
fun HomeScreen(
    uiState : HomeUiState,
    modifier: Modifier = Modifier
) {
    ....
    
    RepeatOnLifecycleEffect(action = { refresh() })
}

This means you do not need HomeUiState.RequiresInitializing.

  • Related