Android-Fragment学习(一)-201810

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:

如果没继承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

 

 

 

猜你喜欢

转载自blog.csdn.net/ever_who/article/details/81176212