Fragment之一:封装及生命周期

一、Fragment是代码和UI的封装(典型的面向对象)

    Fragment是封装逻辑代码和UI的利器,实质上就是一个重写的View(在Fragment中,可以View.findViewByID()),fragment是一种封装、重用的思想,fragment可以动态、灵活的使用UI界面(fragment可以替换)。

    Fragment是UI相对独立一部分(相当于自治区),Fragment不仅有界面,还包含代码块,可接收、处理逻辑事件,甚至还有自己的生命周期,这样有两个好处:一是不必在一个Activity里面写一堆事件、控件的代码,可以通过Fragment实现;二是可以动态的添加、替换、移除某个Fragment,即Activity生命周期和UI界面不变的情况下,可以局部调整fragment所对应的UI部分(自治区)。Fragment是android3.0以后引进的,之前的需要Support兼容包支持。

 

二、Fragment实例化

    每一个Fragment必须有一个无参构造函数,以便实例化Fragment时可以恢复所在Activity的状态,所以Android强烈建议自定义Fragment不要添加有参构造函数,如果希望向Fragment中传递参数,可在构造函数中通过setArguments ()方法设置Bundle,并通过getArgumets()方法获取Bundle并向其中写入传递数据;

    比如调用AFragment时需要传递参数,所以可在AFragment的构造函数中setArguments(new Bundle())设置Bundle:

Public AFragment(){
        super();
// Just to be an empty Bundle. You can usethis later with getArguments() setting datas
          setArguments(new Bundle()); 
       }


    在调用动态调用AFragment时,可以通过getArguments()获取Bundle,并利用putXXX( )传递数据:

Fragment  AFragment= new AFragment();
AFragment.getArguments().putXXX();

    之所以如此麻烦,是因为setArguments()方法仅仅在attached到Activity时才可运行一次,即Fragment仅仅可以实例化一次,即对于某个具体的fragment,其setArguments仅可以执行一次(下面代码的mIndex),否则会出现“Fragment already active”错误,但是通过setArguments()方法设置的Bundle,会贯穿整个Fragment周期直至onDetach(),即使是destroy生命周期也存在。

public void setArguments(Bundleargs) {
    if (mIndex >= 0) {
        throw newIllegalStateException("Fragment already active");
    }
mArguments = args;
}


三、Fragment生命周期

    Fragment共有11个生命周期函数,但只有几个是Activity中没有的新方法,这里需要重点介绍一下:

    onAttach方法:Fragment和Activity建立关联的时候调用。

    onCreateView方法:为Fragment加载布局时调用。

    onActivityCreated方法:当Activity中的onCreate方法执行完后调用作用:1)当需要操作Activity里面的UI;2)需要加载数据或者撤销的时候,应该在此方法操作,而非onActivityView(用户体验)。

    onDestroyView方法:Fragment中的布局被移除时调用。

    onDetach方法:Fragment和Activity解除关联的时候调用,即彻底销毁,相当于Activity的onDestroy()。

 

    Fragment必须是依存于Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。可以将Fragment看作一个View,因此是一个Tree的一个节点,相当于Activity中XML布局的一部分,所以肯定会先创建出节点视图,然后Activity才能形成完整视图。它们的关系可分为三个阶段:

    1)在Activity创建完整视图前,与Activity的生命周期关系是:

    onAttach()-->onCreat()[有些fragment没有视图]-->onCreatView()-->Acitivty.onCreat()-->onActivityCreated()

 

    2)视图创建后,处于活动状态,Activity管理Fragment生命周期,故:

    Activity.onstart()-->onstart()-->Activity.Resume()-->onResume()

    onPause()-->Activity.onPause()-->onStop()-->Activity.onStop()

    3)销毁生命周期

    onDestroyView()-->onDestroy()-->onDetach()-->Activity.onDestroy()

 

    一个包含Fragment的Activity的完整生命周期是上面的顺序,但Fragment是相对独立自主的,所以在动态添加、删除、替换时,Activity的生命周期并不会变化,但就某个fragment而言,可以经历从开始到结束的整个生命周期(当然结果也可以刷新到UI上,有些类似线程操作),这也是fragment的最大优势。

 

四、Fragment加载方式

    1、静态加载Fragment

    这是使用Fragment最简单的一种方式,将Fragment当成一个自定义控件,直接写在Activity的布局文件中,用布局文件调用Fragment,具体可参照自定义控件,有两种方式指定(**是fragment的完整类名):

    1、class=”**”

    2、android:name=”**”

 

2、动态加载fragment,

    可以将Fragment动态加入到一个ViewGroup中,一般外面是FrameLayout布局,可以实现动态的添加、更新、以及删除,这也是fragment最大优势,但是最大的问题就是必须牢记各个操作的生命周期变化,否则经常会出现动态添加的fragment,逻辑操作出现问题。

 

五、Fragment生命周期管理

    Fragment常用的API有三个:

    android.app.Fragment 主要用于定义Fragment;

    android.app.FragmentManager 主要用管理Fragment;

    android.app.FragmentTransaction 保证Fragment操作的原子性,熟悉事务这个词,一定能明白;

 

a、获取FragmentManage的方式:

fm=getFragmentManager()


b、主要的操作都是FragmentTransaction的方法

    FragmentTransactiontransaction = fm.benginTransatcion();//开启一个事务,Fragment之间的添加、替换、移除、隐藏等,对应的生命周期如下:

    add:添加Fragment,从onAttach()运行到onResume()生命周期,add不影响其他fragment的生命周期

    remove:移除Fragment,从onPause()运行到onDetach()

    hide:不改变Fragment的任何生命周期,即什么都不干,所以必须手动在hide后释放fragment资源等等,同理show也是如此,并不会调用生命周期函数

    Replace(fragment1,fragment2),替换时旧有的均会remove销毁,新的add,相当于removeAll与add叠加。

    detach():将此Fragment从Activity中分离,会销毁其布局,但不会销毁该实例;

    attach():将从Activity中分离的Fragment,重新关联到该Activity,重新创建其视图层次

    Detach及attach,我认为用API语言更好描述;

    /**
     * Detach the given fragment from theUI.  This is the same state as
     * when it is put on the back stack: thefragment is removed from
     * the UI, however its state is still beingactively managed by the
     * fragment manager.  When going into this state its view hierarchy
     * is destroyed.
     *
     * @param fragment The fragment to bedetached.
     *
     * @return Returns the sameFragmentTransaction instance.
     */
    public abstract FragmentTransactiondetach(Fragment fragment);
/**Re-attach afragment after it had previously been deatched from the UI withdetach(Fragment). This causes its view hierarchy to be re-created, attached tothe UI, and displayed. */
public abstractFragmentTransaction attach(Fragment fragment);


    上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

必须注意的是:如果你喜欢使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。


a、比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望会到A还能看到数据,则适合你的就是hide和show;也就是说,希望保留用户操作的面板,你可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。


b、再比如:我不希望保留用户操作,你可以使用remove(),然后add();或者使用replace()这个和remove,add是相同的效果。

 

c、remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。

 

六、Fragment回退栈

    管理Fragment回退栈,类似与Android系统为Activity维护一个任务栈,我们也可以通过Activity维护一个回退栈来保存每次Fragment事务发生的变化。如果将Fragment任务添加到回退栈,当用户点击后退按钮时,将看到上一次的保存的Fragment。一旦Fragment完全从后退栈中弹出,用户再次点击后退键,则退出当前Activity。主动将fragment添加到回退栈ft.addToBackStack(frament),ft是事物,回退栈相当于事物回滚。

    比如由remove操作,被移除的fragment只是运行到onDestroyView()生命周期,并没有被完全销毁(??view没有了,所以直接show的话,是没有view的,但是回滚可以)。当回退时,fragment从onCreatVIew()开始,系统会自动保存有ID的系统view数据,但对于自定义控件则无法保存。所以有两个办法:

    1)因为Fragment不会销毁,所以可通过全局变量

    2)将整个rootView整体保存,但是必须去掉其父节点,防止重复添加出错;

两个方法本质上都是设置全局变量,之所以可以,是因为fragment未被销毁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值