Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screens are not paused when app is in the background or when in another Activity #225

Closed
L-Andrade opened this issue Oct 3, 2023 · 4 comments · Fixed by #230
Closed

Comments

@L-Andrade
Copy link

In 1.0.0-rc07, the Screens seem to not pause, for example when we put the app in the background, or when we are in another Activity.

Each Screen will only pause when we move to another screen.

With this sample code:

class MainActivity : ComponentActivity() {
    private val count by lazy { intent?.getIntExtra(COUNT, 0) ?: 0 }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            VoyagerDemoTheme {
                Navigator(Screen1(count))
            }
        }
    }

    companion object {
        private const val COUNT = "COUNT"
        fun getIntent(context: Context, count: Int): Intent =
            Intent(context, MainActivity::class.java).apply { putExtra(COUNT, count) }
    }
}

class Screen1(private val count: Int) : Screen {
    override val key: ScreenKey = uniqueScreenKey

    @Composable
    override fun Content() {
        val lifecycleOwner = LocalLifecycleOwner.current
        val context = LocalContext.current
        val navigator = LocalNavigator.currentOrThrow
        LaunchedEffect(key1 = Unit) {
            Log.d("Screen", "$count started LaunchedEffect from ${context.hashCode()}")
            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
                while (true) {
                    delay(500)
                    Log.d("Screen", "$count is resumed from ${context.hashCode()}")
                }
            }
        }
        Column {
            Text(text = "I am $count")
            Button(
                onClick = { context.startActivity(MainActivity.getIntent(context, count + 1)) }
            ) {
                Text(text = "Start new Activity")
            }
            Button(
                onClick = { navigator.push(Screen1(count + 1)) }
            ) {
                Text(text = "Push new Screen")
            }
        }
    }
}

And the dependencies:

val voyagerVersion = "1.0.0-rc07"
implementation("cafe.adriel.voyager:voyager-navigator:$voyagerVersion")

When we:

  1. Put app in the background
  2. Logs are still being printed -> it means the Composable is still RESUMED when app is in the background
  3. Does not work as expected ❌

When we:

  1. Create a new Activity
  2. Logs from the first Activity are still being printed -> it means the Composable from the first Activity is still RESUMED when its Activity is actually paused
  3. Does not work as expected ❌

When we:

  1. Push a new Screen
  2. Logs from the first screen are no longer printed - the LaunchedEffect was cancelled
  3. Go back
  4. LaunchedEffect is started again because we see the log 0 started LaunchedEffect.
  5. Works as expected ✅

If we rollback to 1.0.0-rc05, with the same sample code, the Screen is paused when we put the app in the background, or when we move to another Activity. The LaunchedEffect themselves are not cancelled, but the repeatOnLifecycle works as expected (they restart when we enter the Screen that is being shown to the user)

@Syer10
Copy link
Contributor

Syer10 commented Oct 3, 2023

Lifecycles are currently directly tied to the screen's Lifecycle, its not tied to the parent Lifecycle yet. That was something I commented on when I improved the Lifecycle integration in #96.

@L-Andrade
Copy link
Author

L-Andrade commented Oct 3, 2023

I see. But that seems to have been added in rc04.

This was working as expected in rc05, but it is not working in rc07. The sample above works in rc05, and it pauses in the background and when moving to another Activity

Edit: Just tested, and it is not working as expected in rc06, so it was something between rc05 and rc06.

@dinarastr
Copy link

This was working as expected in rc05, but it is not working in rc07. The sample above works in rc05, and it pauses in the background and when moving to another Activity

thank you for adding this! had to downgrade for now to support observing the parent lifecycle

@DevSrSouza
Copy link
Collaborator

Is there any way to listen for these lifecycle events in common? I want to prevent flow collection when recomposition happens inside a LaunchedEffect. Thus, I want to do something like lifecycle.owner.repeatOnLifecycle(STARTED).

If not, how would one go about making this work in commonMain properly? An expect composable function that does it for me?

Jetbrains is working on bringing Lifecycle APIs to iOS/KMP, as for now, the recommendation I would give you is to create a expect/actual function for collectWithLifecycle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants