为什么onAttach之前打过onCreate?

时间:2015-04-16 14:29:40

标签: android android-fragments

在Fragment的生命周期中,在onCreate()方法之前调用onAttach()方法。我无法绕过这个。你为什么要先附上一个片段?

4 个答案:

答案 0 :(得分:36)

TL; DR

为了不破坏 Android中不同UI组件之间的设计一致性,onCreate()方法将在所有这些方法中具有类似的功能。

将容器链接到内容(如Window to Activity和Activity to Fragment)时,需要进行初步检查以确定容器的状态。 这解释了onAttach()在片段生命周期中的用法和位置。

太短;需要更长时间:

答案在原型代码本身中,

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

另一个例子是杰克沃顿的ActionBarSherlock图书馆。

为什么要使用onCreate()之类的方法,activityservice具有相同的目的。

onCreate()旨在处理与特定上下文创建有关的问题。如果onCreate()用于检查其容器的状态,则没有意义。

我可以确定的第二个原因是片段被设计为独立于活动。onAttach()提供了一个接口来确定包含的状态/类型/(对片段重要的其他细节)在初始化片段之前参考片段的活动。

修改

活动独立存在,因此具有自我维持的生命周期。

表示片段:

  1. 独立生命周期组件(与任何其他组件相同):

    • 的onCreate()
    • 在onStart()
    • 的onResume()
    • 的onPause()
    • 的onStop()
    • 的onDestroy()
  2. 基于交互的组件:

    • onAttach()
    • onCreateView()
    • onActivityCreated()
    • onDestroyView()
    • onDetach()
  3. 来自documentation

      

    片段生命周期的流程,因为它受其主机的影响   活动,(...)活动的每个连续状态决定哪个   片段可能接收的回调方法。例如,当   activity已经收到了onCreate()回调,一个片段在   活动只接收onActivityCreated()回调。

         

    一旦活动达到恢复状态,您可以自由添加和   删除片段到活动。因此,只有活动在   恢复状态可以改变片段的生命周期   独立地

         

    但是,当活动离开恢复状态时,片段   通过活动再次推动其生命周期。

    回答评论中提出的另一个问题:

      

    警告 :如果片段中需要Context对象,则可以调用getActivity()。但是,只有在片段附加到活动时才要小心调用getActivity()。当片段尚未附加,或在其生命周期结束时被分离时,getActivity()将返回null。

    设计理念指出片段是为重用而设计的。片段(按设计)可以(并且应该)用于多个活动。

    根据定义,onCreate负责创建片段。 考虑方向的情况,你的片段可能是: - 在不同的方向使用不同的布局。 - 仅适用于纵向而非横向 - 仅用于桌子和手机。

    在从android透视图(onCreate())和视图膨胀(onCreateView())初始化片段之前,所有这些情况都需要检查。

    还要考虑headless fragment的情况。onAttach()为您提供初步检查所需的界面。

答案 1 :(得分:13)

因为onAttach()会将托管活动分配给Fragment。如果在onCreate()之后调用它,那么您的片段就没有上下文(getActivity()将返回null),您将无法在onCreate()方法中执行任何操作无论如何,没有这种背景。

另一个合适的原因是Fragment的生命周期类似于Activity的生命周期。在Activity.onAttach()活动中附加到其父级(窗口)。类似地,在Fragment.onAttach()片段附加到其父(活动)之前,在完成任何其他初始化之前。

答案 2 :(得分:9)

这与保留的片段有关。以下片段setRetainInstance(boolean retain)文档:

  

如果设置,重新创建活动时片段生命周期将略有不同:

     
      
  • onDestroy()将不会被调用(但onDetach()仍然会被调用,因为片段正在与其当前活动分离。)
  •   
  • onCreate(Bundle)将不会被调用,因为片段没有被重新创建。
  •   仍然会调用
  • onAttach(Activity)和onActivityCreated(Bundle)。
  •   

看一下源代码(android.support.v4.app.FragmentManager,v21):

void moveToState(Fragment f, 
                 int newState, 
                 int transit, 
                 int transitionStyle,
                 boolean keepActive) {
    ...
    f.onAttach(mActivity);
    if (!f.mCalled) {
        throw new SuperNotCalledException("Fragment " + f
                + " did not call through to super.onAttach()");
    }
    if (f.mParentFragment == null) {
        mActivity.onAttachFragment(f);
    }

    if (!f.mRetaining) {
        f.performCreate(f.mSavedFragmentState); // <- Here onCreate() will be called
    }
    ...
}

实施例

案例1:未保留片段或setRetainInstanceState(false)

应用程序已启动。片段是使用FragmentManager动态添加的,或者是通过setContentView()从XML中扩展的。

onAttach()活动super.onCreate()调用后调用 - 活动已初始化。

MainActivity﹕ call super.onCreate() before
MainActivity﹕ super.onCreate() returned
MainFragment﹕ onAttach() getActivity=com.example.MainActivity@1be4f2dd
MainFragment﹕ onCreate() getActivity=com.example.MainActivity@1be4f2dd

配置已更改。 Activity从已保存状态重新创建片段,从Activity super.onCreate()调用内添加/附加片段:

MainActivity﹕ call super.onCreate() before
MainFragment﹕ onAttach() getActivity=com.example.MainActivity@2443d905
MainFragment﹕ onCreate() getActivity=com.example.MainActivity@2443d905
MainActivity﹕ super.onCreate() returned

案例2:setRetainsInstanceState(true)

应用程序已启动。片段是使用FragmentManager动态添加的,或者是通过setContentView()从XML中扩展的。与上面相同:

onAttach()活动super.onCreate()调用后调用 - 活动已初始化。

MainActivity﹕ call super.onCreate() before
MainActivity﹕ super.onCreate() returned
MainFragment﹕ onAttach() getActivity=com.example.MainActivity@3d54a168
MainFragment﹕ onCreate() getActivity=com.example.MainActivity@3d54a168

配置已更改。

片段onCreate()未调用,但onAttach()仍称为 - 您需要知道,托管活动已更改。但是仍然创建了片段,因此没有调用onCreate()

MainActivity﹕ call super.onCreate() before
MainFragment﹕ onAttach() getActivity=com.example.MainActivity@d7b283e
MainActivity﹕ super.onCreate() returned

答案 3 :(得分:2)

来自Android开发者Site的两点暗示了在片段生命周期的情况下onAttach()之前调用onCreate()的原因。

  1. 片段必须始终嵌入到活动中。现在这意味着Fragment要存在,必须有一个“活着”的活动 此外,当您将片段添加为活动布局的一部分时,它将位于活动视图层次结构内的ViewGroup中。
  2. 因此片段必须首先将“自身”附加到活动以定义自己的视图布局

    1. onCreate被调用以初始创建片段。
    2. 很明显,只有在创建的前提条件到位时才会创建一些东西(并且前提条件是A片段必须始终嵌入到一个活动中,并且它必须附加到其活动中)