最近在看Android 6.0 Settings的源码,Fragment在很多地方都在使用,因此今天有空就复习一下。
一图胜千言,直接看图。(下图来源互联网)
图1、Fragment
图2、Activity
上面是Fragment和Activity(这个很熟悉吧)各自的生命周期,他们有些相同之处。
1、代码片段
MainActivity.java
public class MainActivity extends Activity {
private int[] bt_left_ids = new int[] { R.id.main_bt_first,
R.id.main_bt_second, R.id.main_bt_third };
private First mFist = null;
private Second mSecond = null;
private Third mThird = null;
private static Fragment currentFragment = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
}
private void initUI() {
for (int i = 0; i < bt_left_ids.length; i++) {
findViewById(bt_left_ids[i]).setOnClickListener(clickListener);
}
mFist = new First();
mSecond = new Second();
mThird = new Third();
// 默认显示First
currentFragment = mFist;
setFragment(mFist);
return;
}
private OnClickListener clickListener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.main_bt_first:
setFragment(currentFragment, mFist);
break;
case R.id.main_bt_second:
setFragment(currentFragment, mSecond);
break;
case R.id.main_bt_third:
setFragment(currentFragment, mThird);
break;
default:
break;
}
}
};
/**
* 方法一,这种每次都添加替换,效率低
*
* @param fragment
*/
private void setFragment(Fragment fragment) {
if (null == fragment) {
return;
}
// 如果相同就没必要更新了
if (currentFragment == fragment) {
return;
}
currentFragment = fragment;
// 每次都需要重新初始化
FragmentTransaction mFragmentTransaction = getFragmentManager()
.beginTransaction();
mFragmentTransaction.replace(R.id.main_content, fragment);
mFragmentTransaction.commitAllowingStateLoss(); //
return;
}
/**
* 方法二
*
* @param from
* @param to
*/
private void setFragment(Fragment from, Fragment to) {
// 判断是否相同,如果是就不需要更新
if (from == to) {
return;
}
currentFragment = to;
// 每次都需要重新初始化
FragmentTransaction mFragmentTransaction = getFragmentManager()
.beginTransaction();
// 判断是否已经添加过,如果没有就先添加,在显示
if (!to.isAdded()) {
mFragmentTransaction.hide(from).add(R.id.main_content, to).commit();
} else {
mFragmentTransaction.hide(from).show(to).commit();
}
return;
}
}
First.java
public class First extends Fragment {
private String TAG = "frag";
private View view = null;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.d(TAG, "--First----------onCreate----------");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onCreateView----------");
view = inflater.inflate(R.layout.activity_first, container, false);
return view;
}
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onAttach----------");
super.onAttach(activity);
}
@Override
public void onDetach() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onDetach----------");
super.onDetach();
}
@Override
public void onResume() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onResume----------");
super.onResume();
}
@Override
public void onStart() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onStart----------");
super.onStart();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onStop----------");
super.onStop();
}
@Override
public void onPause() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onPause----------");
super.onPause();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onActivityCreated----------");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onDestroyView() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onDestroyView----------");
super.onDestroyView();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(TAG, "--First----------onDestroy----------");
super.onDestroy();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<Button
android:id="@+id/main_bt_first"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="First" />
<Button
android:id="@+id/main_bt_second"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Second" />
<Button
android:id="@+id/main_bt_third"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="Third" />
</LinearLayout>
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/main_layout" />
</RelativeLayout>
2、生命周期分析
额额,进入退出生命周期就是如下。
1、方法一
setFragment(Fragment fragment)
/**
* 方法一,这种每次都添加替换,效率低
*
* @param fragment
*/
private void setFragment(Fragment fragment) {
if (null == fragment) {
return;
}
// 如果相同就没必要更新了
if (currentFragment == fragment) {
return;
}
currentFragment = fragment;
// 每次都需要重新初始化
FragmentTransaction mFragmentTransaction = getFragmentManager()
.beginTransaction();
mFragmentTransaction.replace(R.id.main_content, fragment);
mFragmentTransaction.commitAllowingStateLoss(); //
return;
}
从Second Fragment 切到 First Fragment,每次切换时都会退出上一个Fragment,这样效率就低了。
#从Second Fragment 切到 First Fragment
--Second----------onCreate----------
--Second----------onCreateView----------
--Second----------onDestroyView----------
--Second----------onDestroy----------
--First----------onAttach----------
--First----------onCreate----------
--First----------onCreateView----------
--First----------onActivityCreated----------
--First----------onStart----------
--First----------onResume----------
2、方法二
setFragment(Fragment from, Fragment to)
/**
* 方法二
*
* @param from
* @param to
*/
private void setFragment(Fragment from, Fragment to) {
// 判断是否相同,如果是就不需要更新
if (from == to) {
return;
}
currentFragment = to;
// 每次都需要重新初始化
FragmentTransaction mFragmentTransaction = getFragmentManager()
.beginTransaction();
// 判断是否已经添加过,如果没有就先添加,在显示
if (!to.isAdded()) {
mFragmentTransaction.hide(from).add(R.id.main_content, to).commit();
} else {
mFragmentTransaction.hide(from).show(to).commit();
}
return;
}
从Second Fragment 切到 First Fragment,第一次进入后会保存,再次切换时就不需要重新加载。
#第一次进入
--First----------onAttach----------
--First----------onCreate----------
--First----------onCreateView----------
--First----------onActivityCreated----------
--First----------onStart----------
--First----------onResume----------
#终结Activity(退出App)
--First----------onPause----------
--First----------onStop----------
--First----------onDestroyView----------
--First----------onDestroy----------
--First----------onDetach----------
3、讲解
以下部分文章摘抄于《Fragment 生命周期的详情》,感谢分享。
onAttach():执行该方法时,Fragment与Activity已经完成绑定,该方法有一个Activity类型的参数,代表绑定的Activity,这时候你可以执行诸如mActivity = activity的操作。
onCreate():初始化Fragment。可通过参数savedInstanceState获取之前保存的值。
onCreateView():初始化Fragment的布局。加载布局和findViewById的操作通常在此函数内完成,但是不建议执行耗时的操作,比如读取数据库数据列表。
onActivityCreated():执行该方法时,与Fragment绑定的Activity的onCreate方法已经执行完成并返回,在该方法内可以进行与Activity交互的UI操作,所以在该方法之前Activity的onCreate方法并未执行完成,如果提前进行交互操作,会引发空指针异常。
onStart():执行该方法时,Fragment由不可见变为可见状态。
onResume():执行该方法时,Fragment处于活动状态,用户可与之交互。
onPause():执行该方法时,Fragment处于暂停状态,但依然可见,用户不能与之交互。
onSaveInstanceState():保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。
onStop():执行该方法时,Fragment完全不可见。
onDestroyView():销毁与Fragment有关的视图,但未与Activity解除绑定,依然可以通过onCreateView方法重新创建视图。通常在ViewPager+Fragment的方式下会调用此方法。
onDestroy():销毁Fragment。通常按Back键退出或者Fragment被回收时调用此方法。
onDetach():解除与Activity的绑定。在onDestroy方法之后调用。