onActivityCreated 已弃用,如何正确使用 LifecycleObserver?

Posted

技术标签:

【中文标题】onActivityCreated 已弃用,如何正确使用 LifecycleObserver?【英文标题】:onActivityCreated is deprecated, how to properly use LifecycleObserver? 【发布时间】:2020-08-02 00:37:55 【问题描述】:

Google 在 android 上弃用 Fragment 的 onActivityCreated() 并推荐使用 LifeCycleObserver:

 To get a callback specifically when a Fragment activity's
     * @link Activity#onCreate(Bundle) is called, register a
     * @link androidx.lifecycle.LifecycleObserver on the Activity's
     * @link Lifecycle in @link #onAttach(Context), removing it when it receives the
     * @link Lifecycle.State#CREATED callback.

所以我尝试以推荐的方式制作它,但我在 Logcat 中只能观察到的状态只是 State: INITIALIZED

 private lateinit var lifecycleObserver: LifecycleObserver

 override fun onAttach(context: Context) 
    super.onAttach(context)

    hostActivity = context as HostActivity

    lifecycleObserver = object : LifecycleObserver 

        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        fun onCreate() 
            Logger.tag("SOME-TAG")d("State: $lifecycle.currentState")

            if(lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)) 
                Logger.tag("SOME-TAG").d("CREATED")
                hostActivity.lifecycle.removeObserver(lifecycleObserver)
            
        
    

    hostActivity.lifecycle.addObserver(lifecycleObserver)

上面的代码有什么问题?

更新 1:看起来我忘了使用 hostActivity.lifecycle.currentState 并检查了片段的生命周期而不是活动生命周期。

更新 2:Google 建议的方法不适用 当您从一个到另一个单击返回按钮时,1 个主机活动和 2 个片段,导致从未调用过 onAttach,但调用了 onActivityCreated。

【问题讨论】:

你找到解决问题的方法了吗?我对谷歌建议的解决方案有同样的问题。想知道我是否误解了他们所说的内容,实际上不应该在那里更新工具栏,而是应该与片段生命周期相关联。 【参考方案1】:

根据更新日志here

onActivityCreated() 方法现已弃用。代码触及 片段的视图应该在onViewCreated() 中完成(称为 紧接在onActivityCreated()) 和其他初始化代码之前 应该在onCreate()。专门接收回调时 活动的onCreate() 已完成,LifeCycleObserver 应该是 在onAttach() 的活动生命周期中注册,并删除一次 收到onCreate() 回调。

你可以在你的片段类中做这样的事情:

class MyFragment : Fragment(), LifecycleObserver 
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreated()
        activity?.lifecycle?.removeObserver(this)
    

    override fun onAttach(context: Context) 
        super.onAttach(context)
        activity?.lifecycle?.addObserver(this)
    

【讨论】:

不同于普通的onActivityCreated()onViewCreated()之后调用,onCreated()方法在onCreateView()之前调用 此解决方案已弃用。我添加了一个当前的解决方案。【参考方案2】:

我用下一个方法做到了:

class MyActivityObserver(
    private val update: () -> Unit
) : DefaultLifecycleObserver 

    override fun onCreate(owner: LifecycleOwner) 
        super.onCreate(owner)
        owner.lifecycle.removeObserver(this)
        update()
    

并在片段 onAttach(或其他生命周期方法)中使用它,例如:

myActivity.lifecycle.addObserver(MyActivityObserver 
    myOnActivityCreated()
)

【讨论】:

【参考方案3】:

您可以将 Lifecycle.State 视为图中的节点,将 Lifecycle.Event 视为这些节点之间的边。

因此,您永远不会在 ON_CREATE 函数上达到 State.Created。

解决方案

class YourFragment : Fragment(), LifecycleObserver 
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onCreated()
        Log.i("tag","reached the State.Created")
    

    override fun onAttach(context: Context) 
        super.onAttach(context)
        lifecycle.addObserver(this)
    

    override fun onDetach() 
        super.onDetach()
        lifecycle.removeObserver(this)
    

更多详情

https://developer.android.com/topic/libraries/architecture/lifecycle#lc

【讨论】:

已弃用的解决方案【参考方案4】:

解决此问题的最佳方法是使用活动生命周期中存在的lifecycleScope。下面是代码sn-p

override fun onAttach(context: Context) 
    super.onAttach(context)
    activity?.lifecycleScope?.launchWhenCreated 
        setupActionbar()
    

它是如何工作的? launchWhenXxx 在启动块自动达到指定状态(在本例中为已创建)时运行启动块,如果生命周期进入销毁状态,它会自动取消启动的协程。 在内部lifecycleScope 使用Dispatchers.Main.immediate,因此没有线程切换的惩罚

这种方法的优点如下:

    您不必手动维护观察者的注册和注销 无需覆盖两个生命周期方法

您必须使用最新的活动和片段依赖项才能使用生命周期附加的生命周期范围

【讨论】:

launchWhenCreated 即将被弃用,最好不要使用它 @Sever 没问题我会一直用最新的技术更新这篇文章。

以上是关于onActivityCreated 已弃用,如何正确使用 LifecycleObserver?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OnActivityCreated 中解决这个不受欢迎的问题?

如何修复已弃用的“按钮样式”

onActivityResult 已弃用如何发送 startResolutionForResult

Flutter - 'showSnackBar' 已弃用 - 如何更新?

如何修复“UIPopoverController 已弃用”警告?

在 Android 中,如何删除已弃用的通知变量?