【问题标题】:Jetpack compose - how do I refresh a screen when app returns to foregroundJetpack compose - 当应用程序返回前台时如何刷新屏幕
【发布时间】:2021-03-09 12:33:19
【问题描述】:

当应用返回前台时,我需要自动刷新 Android Compose 屏幕。

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

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

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

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

【问题讨论】:

    标签: android android-lifecycle android-jetpack-compose


    【解决方案1】:

    我想出了这个:

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

    【讨论】:

    • 一个关于如何使用它的例子会很有帮助
    【解决方案2】:

    我略微改进了 @JojoIV 的回答,并使其在没有回调的情况下保持平稳使用,就像您在撰写 @Abdelilah El Aissaoui 回答的内容中观察到 LiveData 一样

    @Composable
    fun Lifecycle.observeAsSate(): State<Lifecycle.Event> {
        val state = remember { mutableStateOf(Lifecycle.Event.ON_ANY) }
        DisposableEffect(this) {
            val observer = LifecycleEventObserver { _, event ->
                state.value = event
            }
            this@observeAsSate.addObserver(observer)
            onDispose {
                this@observeAsSate.removeObserver(observer)
            }
        }
        return state
    }
    

    然后是用法

    @Composable
    fun SomeComposable() {
       val lifeCycleState = LocalLifecycleOwner.current?.lifecycle?.observeAsSate()
       val state = lifeCycleState?.value
      // will re-render someComposable each time lifeCycleState will change
    }
    

    【讨论】:

      【解决方案3】:

      来自谷歌网站的示例

      @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

      【讨论】:

        【解决方案4】:

        编辑:如果您想要一个“纯粹”的撰写答案,请查看@JoJoIV 's answer

        答案:

        Compose 不知道像onPauseonResume 这样的状态变化,您必须使用父活动的方法来处理它。

        例如,您的活动中的 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 时,属性就会使用新的时间戳进行更新,并且观察可组合对象会被重新组合。

        【讨论】:

        • 谢谢@Abdelilah。这就是我的想法,但我真的希望 Compose 内置一些东西来帮助解决这种情况。我们也使用 Compose 导航构建了我们的应用程序,因此整个应用程序中只有一个 Activity 和一个 Fragment。这是我们遇到的第一个实际问题,但您的解决方案与我们的想法相似,但使用时间戳更好。谢谢。
        【解决方案5】:

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

        @Composable
        fun ComponentActivity.LifecycleEventListener(event: (Lifecycle.Event) -> Unit) {
            val eventHandler by rememberUpdatedState(newValue = event)
            val lifecycle = this@LifecycleEventListener.lifecycle
            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
            }
        })
        

        https://github.com/kafri8889/Notepad-Compose-Android/blob/master/app/src/main/java/com/anafthdev/notepadcompose/utils/ComposeUtils.kt

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-07
          • 1970-01-01
          相关资源
          最近更新 更多