Jetpack Compose – Wie aktualisiere ich einen Bildschirm, wenn die App in den Vordergrund zurückkehrt?

Lesezeit: 5 Minuten

Benutzeravatar von William
Wilhelm

Ich muss einen Android Compose-Bildschirm automatisch aktualisieren, wenn die App in den Vordergrund zurückkehrt.

Ich habe eine, die Berechtigungen und Ortungsdienste erfordert.

Wenn der Benutzer eines davon ausgeschaltet hat, wird eine Liste der Elemente erstellt, die geändert werden müssen. Wenn der Benutzer zu Einstellungen geht und die App in den Vordergrund zurückkehrt, möchte ich, dass die Liste aktualisiert wird, um die Änderungen widerzuspiegeln.

Ich verwende die Compose- und Compose-Navigation. Ich habe nachgesehen und kann das Äquivalent des onResume-Lebenszyklusereignisses nicht herausfinden, das zum Auslösen der Aktualisierung verwendet werden könnte.

Irgendwelche Ideen würden dankbar angenommen, da ich ratlos bin.

Benutzeravatar von JojoIV
JojoIV

Ich bin darauf gekommen:

@Composable
fun OnLifecycleEvent(onEvent: (owner: LifecycleOwner, event: Lifecycle.Event) -> Unit) {
    val eventHandler = rememberUpdatedState(onEvent)
    val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
    
    DisposableEffect(lifecycleOwner.value) {
        val lifecycle = lifecycleOwner.value.lifecycle
        val observer = LifecycleEventObserver { owner, event ->
            eventHandler.value(owner, event)
        }

        lifecycle.addObserver(observer)
        onDispose {
            lifecycle.removeObserver(observer)
        }
    }
}

Es scheint gut zu funktionieren. In manchen Fällen kann es jedoch zu Problemen kommen, seien Sie also vorsichtig.
Es ist auch möglich, dass es einen redundanten Code gibt.

Verwendung:

OnLifecycleEvent { owner, event ->
    // do stuff on event
    when (event) {
        Lifecycle.Event.ON_RESUME -> { /* stuff */ }
        else                      -> { /* other stuff */ }
    }
}

  • Ein Anwendungsbeispiel wäre hilfreich

    – SagaRock101

    1. Januar 2022 um 13:46 Uhr

  • Warum lifecycleOwner muss sich ändern? Ist etw nicht schreibgeschützt?

    – stdout

    4. Juli 2022 um 8:22 Uhr

  • In der Produktion haben wir einige Schleifenprobleme in onResume() beobachtet. dh es ruft den Block Lifecycle.Event.ON_RESUME -> { /* stuff */ } in Schleifen auf

    – Boobalan

    7. Februar um 18:56 Uhr

Benutzeravatar von Arsenius
Arsenius

Ich habe mich leicht verbessert @JojoIV Antwort und machte es flach Verwendung ohne Rückruf, wie Sie beobachten LiveData in komponieren was @Abdelilah El Aissaoui antwortete

@Composable
fun Lifecycle.observeAsState(): State<Lifecycle.Event> {
    val state = remember { mutableStateOf(Lifecycle.Event.ON_ANY) }
    DisposableEffect(this) {
        val observer = LifecycleEventObserver { _, event ->
            state.value = event
        }
        [email protected](observer)
        onDispose {
            [email protected](observer)
        }
    }
    return state
}

und dann Nutzung

@Composable
fun SomeComposable() {
   val lifecycleState = LocalLifecycleOwner.current.lifecycle.observeAsState()
   val state = lifecycleState.value
   // or val lifecycleState by LocalLifecycleOwner.current.lifecycle.observeAsState()
  // will re-render someComposable each time lifecycleState will change
}

  • Diese Antwort war nützlich, wenn nur Resume und Pause verwendet wurden, aber nicht Start und Stop.

    – Bam Bam

    8. November 2022 um 5:44 Uhr

  • @bambam warum ist das so?

    – Josua König

    17. November 2022 um 21:50 Uhr

  • Drucken (die state vor der Rückkehr) und (die event von LifecycleEventObserver) im ersten Ausschnitt . In meinem Fall hieß ersteres nur RESUME und PAUSE. Ich bin mir nicht sicher, aber es scheint, dass es eine Auslassung gibt, indem der Compose-Zustand durchlaufen wird, anstatt das Ereignis sofort zu übergeben. Wenn es sich nicht reproduziert, werde ich weitere Tests durchführen. @JoshuaKing

    – Bam Bam

    18. November 2022 um 2:39 Uhr

Beispiel von der Google-Website

@Composable
fun HomeScreen(
  lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
  onStart: () -> Unit, // Send the 'started' analytics event
  onStop: () -> Unit   // Send the 'stopped' analytics event
) {
    // Safely update the current lambdas when a new one is provided
    val currentOnStart by rememberUpdatedState(onStart)
    val currentOnStop by rememberUpdatedState(onStop)

    // If `lifecycleOwner` changes, dispose and reset the effect
    DisposableEffect(lifecycleOwner) {
        // Create an observer that triggers our remembered callbacks
        // for sending analytics events
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_START) {
                currentOnStart()
            } else if (event == Lifecycle.Event.ON_STOP) {
                currentOnStop()
            }
        }

        // Add the observer to the lifecycle
        lifecycleOwner.lifecycle.addObserver(observer)

        // When the effect leaves the Composition, remove the observer
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    /* Home screen content */
}

Vollständige Beschreibung der Funktionsweise auf der Google-Website
https://developer.android.com/jetpack/compose/side-effects#disposableeffect

Benutzeravatar von Abdelilah El Aissaoui
Abdelila El Aissaoui

Verwendung der offiziellen API (erfordert Lifecycle Runtime Compose 2.7.0):

Warnung: Zum Zeitpunkt des Schreibens (16. März 2023) wurde Lifecycle Runtime Compose 2.7.0 noch nicht veröffentlicht, aber die Änderungen sind bereits im Quellcode enthalten.

Der offizielle Weg zur Erkennung Lifecycle.State Änderungen würden das folgende Code-Snippet verwenden:

val lifecycleOwner = LocalLifecycleOwner.current
val state by lifecycleOwner.lifecycle.collectStateAsState()

LaunchedEffect(state) {
    // Do something with your state
    // You may want to use DisposableEffect or other alternatives 
    // instead of LaunchedEffect
}

collectStateAsState ist eine praktische Erweiterungsfunktion, die Zustandsänderungen mithilfe der neuen Eigenschaft von Lifecycle erfasst currentStateFlow. Der obige Code wäre also der gleiche wie:

val lifecycleOwner = LocalLifecycleOwner.current
val state by lifecycleOwner.lifecycle.currentStateFlow.collectAsState()

LaunchedEffect(state) {
    // Do something with your state
    // You may want to use DisposableEffect or other alternatives 
    // instead of LaunchedEffect
}

Denken Sie daran, zu importieren androidx.compose.runtime.getValue Zu direkt zugreifen Die Lifecycle.State.

Alte Antwort:

Compose kennt keine Zustandsänderungen wie onPause oder onResumemüssen Sie es mit den Methoden der übergeordneten Aktivität handhaben.

Ein Beispiel wäre a LiveData Instanz in Ihrer Aktivität, die jedes Mal aktualisiert wird onResume ausgeführt wird, und beobachten Sie es als Zustand in Ihrem wichtigsten übergeordneten Composable.

Schauen wir uns das folgende Beispiel an:

class MainActivity : AppCompatActivity() {
    // Use whatever type your prefer/require, this is just an example
    private val exampleLiveData = MutableLiveData("")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // Your main composable
            MyApplicationTheme {
                // Save the state into a variable otherwise it won't work
                val state = exampleLiveData.observeAsState()
                Log.d("EXAMPLE", "Recomposing screen - ${state.value}")

                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()

        // Save whatever you want in your live data, this is just an example
        exampleLiveData.value = DateTimeFormatter.ISO_INSTANT.format(Instant.now())
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    MyApplicationTheme {
        Greeting("Android")
    }
}

Wie Sie in diesem Beispiel sehen können, habe ich eine LiveData Eigenschaft in meiner Aktivität, die einen String enthält. Wann auch immer onResume ausgeführt wird, wird die Eigenschaft mit dem neuen Zeitstempel aktualisiert und das beobachtende Composable wird neu zusammengesetzt.

Benutzeravatar von EunhaEonnie
EunhaEonnie

ich habe mich verändert @ojoIV Code dazu (wenn Ihr zusammensetzbarer Code in Aktivität ist)

@Composable
fun ComponentActivity.LifecycleEventListener(event: (Lifecycle.Event) -> Unit) {
    val eventHandler by rememberUpdatedState(newValue = event)
    val lifecycle = [email protected]
    DisposableEffect(lifecycle) {
        val observer = LifecycleEventObserver { _, event ->
            eventHandler(event)
        }
        
        lifecycle.addObserver(observer)
        
        onDispose {
            lifecycle.removeObserver(observer)
        }
    }
}

Verwendung

LifecycleEventListener(event = { lifecycleEvent ->
    when (lifecycleEvent ) {
        Lifecycle.Event.ON_CREATE -> {}
        Lifecycle.Event.ON_START -> {}
        Lifecycle.Event.ON_RESUME -> {}
        Lifecycle.Event.ON_PAUSE -> {}
        Lifecycle.Event.ON_STOP -> {}
        Lifecycle.Event.ON_DESTROY -> {}
        else -> return@LifecycleEventListener
    }
})

  • Hübsch ! Danke ! aber der Link unten ist tot.

    – Mahdi Safarmohammadloo

    5. Juni 2022 um 13:16 Uhr

  • Hübsch ! Danke ! aber der Link unten ist tot.

    – Mahdi Safarmohammadloo

    5. Juni 2022 um 13:16 Uhr

1448900cookie-checkJetpack Compose – Wie aktualisiere ich einen Bildschirm, wenn die App in den Vordergrund zurückkehrt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy