为什么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/(其他细节与片段有关)片段在您初始化一个片段之前。
编辑 :
活动独立存在,因此具有自我维持的生命周期。
对于片段:
-
独立的生命周期组件(与其他组件相同):
- 的onCreate()
- 在onStart()
- 的onResume()
- 的onPause()
- 的onStop()
- 的onDestroy()
-
基于交互的组件:
- 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生命周期。
- 片段必须始终embedded到一个活动中。 现在这意味着片段要存在,必须有一个“活”的活动。
另外,将片段作为活动布局的一部分添加时,它位于活动视图层次结构内的ViewGroup中。
所以Fragment必须首先“附加”自己的活动来定义自己的视图布局
-
onCreate
被调用来做一个片段的初始创build。
很明显,只有当创build的前提条件就绪时,才会创build一些东西(前提条件是A片段必须始终embedded到活动中,并且必须将其附加到其活动中)