Android-Fragment学习 201810
一.Fragment概述
碎片(Fragment)是一种可以嵌入在活动当中的UI片段。我们可以认为碎片是一种子活动。
- 碎片拥有自己的布局,自己的行为及自己的生命周期回调。
- 当活动在运行的时候,你可以在活动中添加或者移除碎片。
- 你可以合并多个碎片在一个单一的活动中来构建多栏的UI。
- 一个碎片可以被用在多个活动中。
- 碎片的生命周期和它的宿主活动紧密关联。这意味着活动被暂停,所有活动中的碎片被停止。
- 碎片可以实现行为而没有用户界面组件。
- 碎片是 Android 3.0 API 11中被加入到 Android API。
Fragment的优势有以下几点:
- 模块化(Modularity):我们不必把所有代码全部写在Activity中,而是把代码写在各自的Fragment中。
- 可重用(Reusability):多个Activity可以重用一个Fragment。
- 可适配(Adaptability):根据硬件的屏幕尺寸、屏幕方向,能够方便地实现不同的布局,这样用户体验更好。
二.Fragment静态加载
1.先创建fragment布局,left_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/frag_bt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
2.然后创建这个类LeftFragment
public class LeftFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.left_fragment,container,false);
}
}
类似地,可以创建right_fragment.xml和RightFragment类。
3.修改activity的布局文件,activity类
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.hjc.hello2.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<fragment
android:id="@+id/right_fragment"
android:name="com.example.hjc.hello2.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</LinearLayout>
public class SixthActivity extends FragmentActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sixth);
}
}
注:fragment有两个android.support.v4.Fragment和android.app.Fragment,建议使用v4包的。
原因:可以让所有android系统保持功能一致性,比如在Fragment中嵌套使用Fragment在Android 4.2并不支持
使用v4.Fragment时,注意android.support.v4.Fragment注释中的一段话:
The main differences when using this support version instead of the framework version are:
- Your activity must extend
FragmentActivity ---
activity必须继承FragmentActivity
- You must call
getSupportFragmentManager()
to get theFragmentManager
--获取FragmentManager需要用getSupportFragmentManager()
方法
如果没继承FragmentActivity类,
会报错android.view.InflateException: Binary XML file line #33: Error inflating class fragment。
虽然Fragment能在XML中添加,但是这只是一个语法糖而已,Fragment并不是一个View,而是和Activity同一层次的。
三.Fragment动态加载
Fragment核心的类有:
- Fragment:Fragment的基类,任何创建的Fragment都需要继承该类。
- FragmentManager:管理和维护Fragment。他是抽象类,具体的实现类是FragmentManagerImpl。
- FragmentTransaction:对Fragment的添加、删除等操作都需要通过事务方式进行。他是抽象类,具体的实现类是BackStackRecord。
1.修改activity的layout,这里需要使用一个容器存放fragment,一般可以使用FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/left_fragment"
android:name="com.example.hjc.hello2.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<FrameLayout
android:id="@+id/right_fragment"
android:name="com.example.hjc.hello2.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
</LinearLayout>
2.在activity类onCreate方法中添加这个fragment
public class SixthActivity extends FragmentActivity implements View.OnClickListener{
private int index=1;
private List<Fragment> fragList=new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sixth);
Button frag_bt=findViewById(R.id.frag_bt1);
frag_bt.setOnClickListener(this);
//newInstance-就是在new RightFragment()
fragList.add(RightFragment2.newInstance("r2"));
fragList.add(RightFragment.newInstance("r1"));
replace(fragList.get(0));
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.frag_bt1:
replace(fragList.get(index));
index=1-index;
break;
default:
break;
}
}
//切换fragment
private void replace(Fragment fragment){
//获取FragmentManager管理类
FragmentManager fragmentManager=getSupportFragmentManager();
//打开Fragment事务
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
//replace移除当前容器内所有fragment,添加一个新的fragment
fragmentTransaction.replace(R.id.right_fragment,fragment,"switcher");
//提交事务
fragmentTransaction.commit();
}
}
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment, @Nullable String tag)-参数(容器的ID,添加的fragment,tag标签)
指定过tag的fragment,可以通过FragmentManager的findFragmentByTag(String tag)方法获取到该fragment对象.
除了replace方法外,FragmentTransaction中还有add,remove等方法。一次事务中可以提交多个操作。这个和数据库的事务的一样的,但是这里没有rollback。只有回退栈(BackStack),可以通过addToBackStack(String name)加入回退栈,加入后按返回键会回退上一次的commit(原来按返回是结束当前activity)。一般就写在commit前面。name这个参数可选,一般就传null。
//切换fragment
private void replace(Fragment fragment){
//获取FragmentManager管理类
if(fragmentManager==null){
fragmentManager=getSupportFragmentManager();
}
//打开Fragment事务
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
//replace移除当前容器内所有fragment,添加一个新的fragment
fragmentTransaction.replace(R.id.right_fragment,fragment,FRAG_TAG);
//加入回退栈test
fragmentTransaction.addToBackStack("test");
//提交事务
fragmentTransaction.commit();
}
注意:
1.使用FragmentTransaction.add方法时,不能重复添加已有的fragment,否则会报java.lang.IllegalStateException: Fragment already added: RightFragment2{b15aabf #1 id=0x7f070067 switcher}。
2.commit()方法是异步操作,可以添加多个动作,一次提交。内部通过mManager.enqueueAction()
加入处理队列。对应的同步方法是commitNow()方法。
3.commit()方法必须在onSaveInstance方法调用前使用。原因是:若在onSaveInstance之后提交,恢复数据时,可能与commit的结果产生冲突。
四.生命周期(转)
Fragment的生命周期和Activity类似,但比Activity的生命周期复杂一些,基本的生命周期方法如下图:
解释如下:
- onAttach():Fragment和Activity相关联时调用。可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。
- onCreate():Fragment被创建时调用。
- onCreateView():创建Fragment的布局。
- onActivityCreated():当Activity完成onCreate()时调用。
- onStart():当Fragment可见时调用。
- onResume():当Fragment可见且可交互时调用。
- onPause():当Fragment不可交互但可见时调用。
- onStop():当Fragment不可见时调用。
- onDestroyView():当Fragment的UI从视图结构中移除时调用。
- onDestroy():销毁Fragment时调用。
- onDetach():当Fragment和Activity解除关联时调用。
上面的方法中,只有onCreateView()在重写时不用写super方法,其他都需要。
因为Fragment是依赖Activity的,因此为了讲解Fragment的生命周期,需要和Activity的生命周期方法一起讲,即Fragment的各个生命周期方法和Activity的各个生命周期方法的关系和顺序,如图:
参考:
https://developer.android.google.cn/guide/components/fragments
https://cloud.tencent.com/developer/article/1005538
https://xiazdong.github.io/2017/06/15/android-fragment/
https://blog.csdn.net/u011734444/article/details/53347265