0%

Fragment不完全解析

Fragment是在Android 3.0 (API level 11)开始引入的,它能让你的app在现有基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fragment要多,响应速度Fragment比Activty在中低端手机上快了很多,甚至能达到好几倍,同时给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持.


一、Fragment的生命周期

Fragment表示Activity中的行为或用户界面部分,其生命周期直接受宿主activity生命周期的影响。下图可以很直观反映出两者的关系:

Fragment VS Activity

Fragment比Activity多出的几个生命周期回调方法:

  • onAttach(Activity)

    called once the fragment is associated with its activity.(当Fragment和Activity相关联调用

  • onCreateView(LayoutInflater, ViewGroup, Bundle)

    creates and returns the view hierarchy associated with the fragment.(创建Fragment的视图

  • onActivityCreated(Bundle)

    tells the fragment that its activity has completed its own Activity.onCreate(). (当Activity.onCreate()完成时调用

  • onDestroyView()

    allows the fragment to clean up resources associated with its View.

  • onDetach()

    called immediately prior to the fragment no longer being associated with its activity

二、Fragment 的使用

静态使用

把Fragment当做普通的控件写入Activity的布局文件中,用布局文件调用Fragment,这里不再展开

动态使用

Fragment动态使用主要是动态添加,更新,删除.

在activity的布局文件中添加一个FrameLayout,作为fragment需要放入的ViewGroup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="net.december1900.test.MainActivity">

<FrameLayout
android:id="@+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</RelativeLayout>

fragment和主activity

1
2
3
4
5
6
7
8
9
public class MainFragment extends Fragment{

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main,container,false);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {

private MainFragment mMainFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showFragment();
}

private void showFragment(){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
mMainFragment = new MainFragment();
fragmentTransaction.replace(R.id.content_layout,mMainFragment);
fragmentTransaction.commit();
}
}

显示

Fragment常用的类

  1. android.app.FragmentManager

    获取方式:getSupportFragmentManager();

  2. android.app.FragmentTransaction

    FragmentTransaction transaction = fm.benginTransatcion();

    • transaction.add()

      往Activity中添加一个Fragment

    • transaction.remove()

      从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁

    • transaction.replace()

      使用另一个Fragment替换当前的,可以理解为remove() + add()

    • transaction.hide()

      隐藏当前的Fragment,仅仅是设为不可见,并不会销毁

    • transaction.show()

      显示之前隐藏的Fragment

    • transatcion.commit()

总结起来:

如果你希望保留用户操作的面板,可以使用show(),hide()。其实是让Fragment的View setVisibility(true还是false),不会调用生命周期

如果你不希望保留用户操作,可以使用replace()。其会销毁视图,即调用onDestoryView、onCreateView等一系列生命周期

三、管理Fragment的回退栈

我们可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。如果将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则会退出当前Activity。

添加一个Fragment事务到回退栈:
FragmentTransaction.addToBackStack(String)

主activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MainActivity extends AppCompatActivity {

private MainFragment mMainFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showFragment("MainFragment");
}

private void showFragment(String tag) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
mMainFragment = new MainFragment();
fragmentTransaction.add(R.id.content_layout, mMainFragment, tag);
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();

}

}

MainFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MainFragment extends Fragment {

@BindView(R.id.btn_main)
Button mBtnMain;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
ButterKnife.bind(this, view);
return view;
}


@OnClick(R.id.btn_main)
public void onViewClicked() {

showFragment("SecondFragment");
}

private void showFragment(String tag) {
SecondFragment secondFragment = new SecondFragment();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.content_layout, secondFragment, tag);
transaction.addToBackStack(tag);
transaction.commit();

}
}

SecondFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class SecondFragment extends Fragment {

@BindView(R.id.btn_second)
Button mBtnSecond;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
ButterKnife.bind(this, view);
return view;
}


@OnClick(R.id.btn_second)
public void onViewClicked() {
showFragment("ThirdFragment");
}

private void showFragment(String tag) {
ThirdFragment thirdFragment = new ThirdFragment();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.content_layout, thirdFragment, tag);
transaction.addToBackStack(tag);
transaction.commit();
}
}

显示

总体来说,我们调用addToBackStack(tag);将当前的事务添加到了回退栈,所以MainFragment实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView,但是使用add()方法的SecondFragment视图层依然存在