为什么onAttach在onCreate之前调用?

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

TL; DR

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

当将容器连接到像Window这样的内容到活动和活动到片段时,需要做一个初步的检查来确定容器的状态。 这解释了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()这样的方法,它在activity , service中具有相同的用途。

onCreate()意味着处理与特定上下文创build有关的问题。如果使用onCreate()来检查其容器的状态,这是没有意义的。

我可以决定的第二个原因是一个片段被devise为独立的活动onAttach()提供了一个接口来确定包含活动的状态/types/(其他细节与片段有关)片段在您初始化一个片段之前。

编辑

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

对于片段:

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

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

    • onAttach()
    • onCreateView()
    • onActivityCreated()
    • onDestroyView()
    • onDetach()

从文档 :

一个片段生命周期的stream程,因为它受到宿主活动的影响,(…)每个连续的活动状态决定了一个片段可能接收哪个callback方法。 例如,当活动接收到onCreate()callback时,活动中的一个片段只能收到onActivityCreated()callback。

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

然而,当活动离开恢复状态时,片段再次被活动推到整个生命周期。

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

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

devise理念指出,片段是为了重用而devise的。 片段(按devise)可以(也应该)跨多个活动使用。

按定义onCreate负责创build一个片段。 考虑定位的情况,你的片段可能是: – 在不同的方向使用不同的布局。 – 仅适用于纵向和横向 – 仅用于桌子和手机。

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

还要考虑一个无头碎片的情况onAttach()为您提供初步检查所需的界面。

因为onAttach()将托pipe活动分配给Fragment 。 如果它在onCreate()之后被调用,那么你的片段将没有上下文( getActivity()将返回null ),并且无论如何也不能在onCreate()方法中做任何事情。

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

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

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

  • onDestroy()将不会被调用(但onDetach()仍然会,因为片段正在从它当前的活动分离)。
  • onCreate(Bundle)将不会被调用,因为片段不被重新创build。
  • 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)

应用程序已启动。 使用FragmentManagerdynamic添加片段,或者通过setContentView()从XML中setContentView()片段。

onAttach() 调用Activity 之后调用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 

configuration已更改。 活动重新创build保存状态的片段,从内部添加/附加片段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)

应用程序已启动。 使用FragmentManagerdynamic添加片段,或者通过setContentView()从XML中setContentView()片段。 同上:

onAttach() 调用Activity 之后调用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 

configuration已更改。

片段onCreate()没有被调用,但onAttach()仍然被调用 – 你需要知道,托pipe活动已经改变。 但仍然是片段已经创build,所以没有onCreate()调用。

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

来自Android开发者的两点关于为什么onAttach()onCreate()之前被调用,以防Fragment生命周期。

  1. 片段必须始终embedded到一个活动中。 现在这意味着片段要存在,必须有一个“活”的活动。
    另外,将片段作为活动布局的一部分添加时,它位于活动视图层次结构内的ViewGroup中。

所以Fragment必须首先“附加”自己的活动来定义自己的视图布局

  1. onCreate被调用来做一个片段的初始创build。

很明显,只有当创build的前提条件就绪时,才会创build一些东西(前提条件是A片段必须始终embedded到活动中,并且必须将其附加到其活动中)