在Fragment的生命周期中,在onCreate()方法之前调用onAttach()方法。我无法绕过这个。你为什么要先附上一个片段?
答案 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()
之类的方法,activity,service具有相同的目的。
onCreate()
旨在处理与特定上下文创建有关的问题。如果onCreate()
用于检查其容器的状态,则没有意义。
我可以确定的第二个原因是片段被设计为独立于活动。onAttach()
提供了一个接口来确定包含的状态/类型/(对片段重要的其他细节)在初始化片段之前参考片段的活动。
修改强>:
活动独立存在,因此具有自我维持的生命周期。
表示片段:
独立生命周期组件(与任何其他组件相同):
基于交互的组件:
片段生命周期的流程,因为它受其主机的影响 活动,(...)活动的每个连续状态决定哪个 片段可能接收的回调方法。例如,当 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()
的原因。
因此片段必须首先将“自身”附加到活动以定义自己的视图布局
onCreate
被调用以初始创建片段。 很明显,只有在创建的前提条件到位时才会创建一些东西(并且前提条件是A片段必须始终嵌入到一个活动中,并且它必须附加到其活动中)