Jetpack compose - 当应用返回前台时如何刷新屏幕

问题描述 投票:0回答:5

我需要在应用程序返回前台时自动刷新 Android Compose 屏幕。

我有一个需要权限和定位服务。

如果用户关闭了其中的任何一个,则会绘制一个列表,列出需要更改的项目。当用户转到“设置”并且应用程序返回到前台时,我希望列表能够刷新以反映更改。

我正在使用 Compose 和 Compose 导航。我已经看过,但我无法弄清楚可用于触发刷新的 onResume 生命周期事件的等价物。

任何想法都将不胜感激,因为我不知所措。

android android-lifecycle android-jetpack-compose
5个回答
71
投票

我想出了这个:

@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)
        }
    }
}

似乎工作得很好。但在某些情况下可能会出现一些问题,所以要小心。
也有可能是有些多余的代码。

用法:

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

39
投票

我稍微改进了 @JojoIV 答案并使它在没有回调的情况下使用平坦,就像您观察到的

LiveData
在撰写@Abdelilah El Aissaoui 回答的内容

@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
}

然后使用

@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
}

20
投票

来自谷歌网站的例子

@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 */
}

在谷歌网站上的完整描述 https://developer.android.com/jetpack/compose/side-effects#disposableeffect


5
投票

使用官方 API(需要 Lifecycle Runtime Compose 2.7.0):

警告: 在撰写本文时(2023 年 3 月 16 日)Lifecycle Runtime Compose 2.7.0 尚未发布,但更改已在源代码中。

检测

Lifecycle.State
变化的官方方法是使用以下代码片段:

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
是一个便利的扩展函数,它通过使用 Lifecycle 的新属性
currentStateFlow
来收集状态变化。所以上面的代码和做的一样:

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
}

记得导入

androidx.compose.runtime.getValue
直接访问
Lifecycle.State
.

旧答案:

Compose 不知道像

onPause
onResume
这样的状态变化,你必须使用父活动的方法来处理它。

一个例子是您的 Activity 中的一个

LiveData
实例,它会在每次执行
onResume
时更新,并将其作为主要父可组合项中的状态进行观察。

我们来看下面的例子:

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")
    }
}

如您在此示例中所见,我的活动中有一个包含字符串的

LiveData
属性。每当执行
onResume
时,属性都会更新为新的时间戳,并且观察可组合项会重新组合。


3
投票

我把@ojoIV代码改成了这个 (如果您的可组合代码在 Activity 中)

@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)
        }
    }
}

用法

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
    }
})
© www.soinside.com 2019 - 2024. All rights reserved.