来自文档 https://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity):
void onAttach(活动活动)
一旦片段与其活动相关联,就会调用。此方法在 API 级别已被弃用
23. 使用 onAttach(Context) 代替。
如果重写此方法,则必须调用超类
执行。
void onAttach(上下文上下文)
当片段首次附加到其上下文时调用。 onCreate(Bundle) 将在此之后调用。
这是片段的生命周期设计。当您不重写该方法时,没有什么问题。
所有片段回调的默认定义是否已经存在?
不,您需要自己创建片段回调。onAttach()
方法通常被重写以确保片段的父活动正在实现片段回调。像这样的东西(阅读更多内容与其他片段通信 https://developer.android.com/guide/fragments/communicate):
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnHeadlineSelectedListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
当父 Activity 未执行时OnHeadlineSelectedListener
,应用程序将崩溃并抛出must implement OnHeadlineSelectedListener
。因此,它将防止您在代码中引入逻辑错误。
UPDATE
目的是什么onAttach()
?
根据片段生命周期 onAttach() 在 onCreate() 之前调用
以便它将托管活动分配给片段。
这实际上意味着什么?
简单的答案:这是 Fragment 的生命周期,我们可以知道 Fragment 何时附加到其父 Activity。
更多细节:
从以下内容的源代码onAttach() https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/app/Fragment.java#L1563:
/**
* Called when a fragment is first attached to its context.
* {@link #onCreate(Bundle)} will be called after this.
*/
@CallSuper
public void onAttach(Context context) {
mCalled = true;
final Activity hostActivity = mHost == null ? null : mHost.getActivity();
if (hostActivity != null) {
mCalled = false;
onAttach(hostActivity);
}
}
/**
* @deprecated Use {@link #onAttach(Context)} instead.
*/
@Deprecated
@CallSuper
public void onAttach(Activity activity) {
mCalled = true;
}
除了有关我们之前问题的文档之外,我们什么也看不到mHost
.
Fragment 的源代码位于https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/Fragment.java#L435 https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/Fragment.java#L435,我们可以知道mhost
实际上是一个FragmentHostCallback
:
// Activity this fragment is attached to.
FragmentHostCallback mHost;
但是如果我们扫描所有的源代码Fragment,我们将无法得到任何线索mhost
已初始化。
从Fragment生命周期图中我们知道,生命周期是从fragment被添加的时候开始的:
我们以编程方式添加片段:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
检查FragmentManager源代码第1200到1229行 https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/app/FragmentManager.java#L1220从方法moveToState()
:
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
}
我们有以下代码:
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
// If we have a target fragment, push it along to at least CREATED
// so that this one can rely on it as an initialized dependency.
if (f.mTarget != null) {
if (mActive.get(f.mTarget.mIndex) != f.mTarget) {
throw new IllegalStateException("Fragment " + f
+ " declared target fragment " + f.mTarget
+ " that does not belong to this FragmentManager!");
}
if (f.mTarget.mState < Fragment.CREATED) {
moveToState(f.mTarget, Fragment.CREATED, 0, 0, true);
}
}
dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
f.mCalled = false;
f.onAttach(mHost.getContext());
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
现在我们知道了mHost
and onAttach()
Fragment 的初始化和调用由FragmentManager
.