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

66

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中观察到的仅仅是状态:已初始化

 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被调用。


你找到解决后退问题的方法了吗?我使用谷歌建议的解决方案仍然存在同样的问题。不知道是不是我误解了他们的意思,实际上更新工具栏不应该在那里发生,而应该与片段生命周期相关联。 - Alex
5个回答

53

根据此处的更新日志:

onActivityCreated() 方法现已弃用。涉及片段视图的代码应在 onViewCreated() 中完成(该方法会在 onActivityCreated() 之前立即调用),其他初始化代码应在 onCreate() 中完成。要在活动的 onCreate() 完成时接收回调,应在 onAttach() 中向活动的生命周期注册一个 LifeCycleObserver ,并在收到 onCreate() 回调后将其删除。

在您的片段类中,可以这样做:

class MyFragment : Fragment(), LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreated() {
        // ... Your Logic goes here ...
    }

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

    override fun onDetach() {
        activity?.lifecycle?.removeObserver(this)
        super.onDetach()
    }
}

5
与通常在onViewCreated()之后调用的onActivityCreated()不同,onCreated()方法是在onCreateView()之前调用的。 - Misagh Emamverdi
此解决方案已过期。我添加了一个当前的解决方案。 - S. Gissel
2
d = (◕‿↼) 真遗憾!现在@OnLifecycleEvent注释已经被弃用了,文档建议使用DefaultLifecycleObserverLifecycleEventObserver - Top-Master
3
有人告诉谷歌,要做出决定并且不再随意翻译,而是按照标准进行翻译。 - Top-Master
1
当前解决方案在哪里 @S.Gissel - Gabriel Rogath

19

我所需要的就是 onActivityCreated(...),因此我实现了一个观察器:

  • 自动删除自身(使用 .removeObserver(...))。
  • 然后调用传递的回调函数(update())。

我是这样做的:

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

但是为了支持旧版的Android API级别,你的Activity需要是androidxAppCompatActivity类型(它有getLifecycle()),或者使用一个简单的@SuppressWarnings("deprecation")


2
此方法将在 LifecycleOwner 的 onCreate 方法返回后被调用。请参考:https://developer.android.com/reference/androidx/lifecycle/DefaultLifecycleObserver#onCreate(androidx.lifecycle.LifecycleOwner) - Sever
我理解得对吗?如果我创建一个多触发回调的解决方案(例如 onResume - 此状态可以在生命周期内被多次调用),那么回调只会工作一次,因为在第一次触发后,它就会被退订。也许在最新的生命周期回调'onDestroy'中进行退订更好? - neronovs

9
您可以将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


弃用的解决方案 - S. Gissel
1
@OnLifecycleEvent 已经过时!! - C.F.G

7
最好的解决方法是使用lifecycleScope,它存在于活动生命周期中。以下是代码片段。
override fun onAttach(context: Context) {
    super.onAttach(context)
    activity?.lifecycleScope?.launchWhenCreated {
        setupActionbar()
    }
}

它是如何工作的?当launchWhenXxx自动到达指定的状态(在这种情况下是Created)时,它会运行启动块,并且如果生命周期到达了Destroyed状态,则会自动取消已启动的协程。内部使用lifecycleScopeDispatchers.Main.immediate,因此没有线程切换的惩罚。
该方法的优点如下:
  1. 不需要手动维护观察者的注册和注销
  2. 不需要覆盖两个生命周期方法
您需要使用最新的Activity和Fragment依赖项才能使用附加到生命周期的lifecycleScope。

launchWhenCreated 将很快被弃用,最好不要使用它。 - Sever
@服务器 没问题,我会随时更新这篇文章,使用最新的技术。 - AndroidEngineX
已弃用 - undefined
嗨,@PedroVarela 更新了代码。非常感谢你的提醒。如果你有任何反馈,请告诉我。 - undefined

1

onActivityCreated 已在 API 级别 28 中不推荐使用。

使用 onViewCreated 处理涉及由 onCreateView 创建的视图的代码, 并使用 onCreate 进行其他初始化。要在 Fragment 活动的 onCreate 被调用时获得特定回调,请在 onAttach 中在 Activity 生命周期中注册 androidx.lifecycle.LifecycleObserver,并在收到 CREATED 回调时将其删除。

注释 @OnLifecycleEvent 也已过时。

此注释要求使用代码生成或反射,应避免使用。改用 DefaultLifecycleObserverLifecycleEventObserver

最简单的解决方案:通常情况下,大多数情况下,可以通过将代码移动到 onViewCreated 中解决 onActivityCreated 问题。如果这对您不起作用,请继续向下阅读。

====================================================================

因此,为了解决已弃用的onActivityCreatedOnLifecycleEvent注释问题,您应该执行以下操作:

  1. 实现DefaultLifecycleObserver
  2. onAttach()中将您的类注册为观察者。
  3. 重写onCreate(owner: LifecycleOwner)并将您的代码从onActivityCreated移动到其中。
  4. onCreate()中接收到CREATE事件时取消注册观察者。

请参见以下Kotlin和Java示例:

Kotlin:

class YourFragment : Fragment(), DefaultLifecycleObserver {

    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Register your class as observer
        activity?.lifecycle?.addObserver(this)
    }

    override fun onCreate(owner: LifecycleOwner) {
        super<DefaultLifecycleObserver>.onCreate(owner)
        // Remove the observer
        activity?.lifecycle?.removeObserver(this)

        //Move here your code from onActivityCreated(savedInstanceState: Bundle?) 

    }

}

Java:

public class YourFragment extends Fragment implements DefaultLifecycleObserver {

    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        // Register your class as observer
        if (getActivity() != null) {
            getActivity().getLifecycle().addObserver(this);
        }
    }

    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onCreate(owner);
        // Remove the observer
        if (getActivity() != null) {
            getActivity().getLifecycle().removeObserver(this);
        }

        //Move here your code from onActivityCreated(savedInstanceState: Bundle?) 

    }

重要提示:请注意,onActivityCreatedonCreateView 之后调用,但是 DefaultLifecycleObserver.onCreateonCreateView 之前调用。因此,如果您在 onActivityCreated 中使用了在 onCreateView 中初始化的内容,您将不得不将其移动到其他地方。例如,在 onViewCreated() 中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接