为什么需要Fragment?
在官方文档的翻译中,Fragment译为片段。那么它是谁的片段?当然是Activity的,其目的在于解决如下几个问题:
- 将臃肿的Activity类分解为小的Fragment
- 修复老版本中
LocalActivityManager
所带来的问题 - 封装导航状态,如Activity本地回退栈和可管理的对话框(DialogFragment)
- 分离主从式UI(Master/Detail)
Fragment的功能
- 生命周期
- 回退栈管理
- 配置改变时保留实例
- FragmentManager的状态管理
- 管理一个视图
- 在xml布局中使用
<fragment>
如何高效使用Fragment
尽管在布局中可以使用<fragment>
标签,但并不能将其等效为View
。从它所位于的抽象层级上而言其等效于Activity
,是位于View
之上的,其中Android包之间的抽象层级如下所示:
高层级 | android.app
| android.widget
低层级 | android.view
v android.content
尽管AOSP中的代码可能并非严格遵循这一规则,但大体上如此。Fragment依赖于View的界面绘制与事件响应,但View对Fragment一无所知,Fragment拥有View之外的关于生命周期的知识,可以协调View之间的协作。
Fragment状态
实际上并不用去记忆Fragment复杂的生命周期,它的状态实际上由若干整形值进行标识,并且其状态转换基本上是一个线性的顺序:
static final int INITIALIZING = 0; // Not yet created.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3; // Fully created, not started.
static final int STARTED = 4; // Created and started, not resumed.
static final int RESUMED = 5; // Created started and resumed.
一个Fragment的生命周期回调的一般顺序如下所示:
生命周期回调 | 描述 |
---|---|
onInflate | |
onAttach | |
onAttachFragment | |
onCreate | |
onCreateView | |
onActivityCreated | |
onStart | |
onResume | |
onStop | |
onDestoryView | |
onDestory | |
onDetach |
DialogFragment
show()
/**
* Display the dialog, adding the fragment to the given FragmentManager. This
* is a convenience for explicitly creating a transaction, adding the
* fragment to it with the given tag, and {@link FragmentTransaction#commit() committing} it.
* This does <em>not</em> add the transaction to the fragment back stack. When the fragment
* is dismissed, a new transaction will be executed to remove it from
* the activity.
* @param manager The FragmentManager this fragment will be added to.
* @param tag The tag for this fragment, as per
* {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
*/
public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}
/**
* Display the dialog, adding the fragment using an existing transaction
* and then {@link FragmentTransaction#commit() committing} the transaction.
* @param transaction An existing transaction in which to add the fragment.
* @param tag The tag for this fragment, as per
* {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
* @return Returns the identifier of the committed transaction, as per
* {@link FragmentTransaction#commit() FragmentTransaction.commit()}.
*/
public int show(FragmentTransaction transaction, String tag) {
mDismissed = false;
mShownByMe = true;
transaction.add(this, tag);
mViewDestroyed = false;
mBackStackId = transaction.commit();
return mBackStackId;
}
展示对话框,这里将fragment添加到FragmentManager中。
dimiss()
/**
* Dismiss the fragment and its dialog. If the fragment was added to the
* back stack, all back stack state up to and including this entry will
* be popped. Otherwise, a new transaction will be committed to remove
* the fragment.
*/
public void dismiss() {
dismissInternal(false);
}
void dismissInternal(boolean allowStateLoss) {
if (mDismissed) {
return;
}
mDismissed = true;
mShownByMe = false;
if (mDialog != null) {
mDialog.dismiss();
}
mViewDestroyed = true;
if (mBackStackId >= 0) {
getFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
}
}
这里会将fragment从回退栈中弹出,或者从FragmentManager中移除。这里fragment会走完剩余的全部生命周期。