zoukankan      html  css  js  c++  java
  • fragment之基本总结

    16.fragment与activity交互方式?

    15.fragment保存数据?

    14.Fragment的事务 与 fragment的回退栈?

    13.给Fragment设置参数?

    12.对于Fragment的一些操作对生命周期的影响

    11.fragment生命周期:

    ======

    15.fragment保存数据?

    与Activity类似,你可以利用Bundle来记录Fragment的状态,当Activity被销毁需要记录Fragment状态,并且在Activity重新创建的时候恢复Fragment的状态。
    你可以保存Fragment的状态在Fragment的onSaveInstanceState()回调方法中,在onCteate()、onCreateView()或者onActivityCreated()方法中进行恢复。

    但是因为Fragment依附于Activity。
    所以,关于Fragment创建的生命周期总是在Activity之后调用,关于Fragment销毁的生命周期总是在Activity之前调用。
    除此之外,在Activity需要重新创建的时候,fragment和activity一样可以通过onSaveInstanceState来保存状态,然后在onCreate,onCreateView或者onActivityCreated期间恢复状态。

    注意:在Fragment中你如果要获取一个Context对象,你可以调用getActivity()方法,但是调用getActivity()方法必须要在Fragment于Activity关联起来之后,否则getActivity()返回为null。

    14.Fragment的事务 及 fragment的回退栈?

     FragmentTransaction也就是fragment的事务,这对我们理解生命周期有很重要的作用。
    那么什么是事务?
    根据用户的交互情况, 对fragment进行添加(add)、移除(remove)、替换(replace),以及执行其他动作,提交给activity的每一套变化,被称为一个事务。

    事务当中存在一个堆栈的数据结构,它允许用户经由fragment的变化往回导航(就是和activity回跳类似,这和activity之间跳转实现都是一样的,均用堆栈实现)。

    用户可以通过添加FragmentTransaction.addToBackStack(null)函数(一定要在FragmentTrasaction.commit()之前调用),将此Fragment添加到后台堆栈。

    在生命周期中Activity与Fragment的最大不同之处是回退栈是相互独立的,Activity的回退栈是系统来管理的,Fragment的回退栈是被宿主Activity来管理的,也就是说你可以来进行控制(调用addToBackStack()).

    13.给Fragment设置参数

    使用setArguments,在创建Fragment的时候传递参数,然后在fragment的onCreate方法处获取参数,但是需要注意的是setArguments()方法必须在fragment创建以后,add之前调用。这样的好处是对Fragment的代码进行管理

    //流行一种做法是使用静态方法newInstance()的方式来初始化Fragment
    public static CircleFragmetn newInstance(String str){
    Bundle bundle = new Bundle();
    bundle.putString("data", str);
    CircleFragmetn fragment = new CircleFragmetn();
    fragment.setArguments(bundle);
    return fragment;
    }

    没有UI的Fragment
    可以添加没有UI的Fragment,使用add(Fragment,String)向Activity添加片段,由于它不与Activity布局的视图关联,所以不会触发onCreateView。通常没有UI的Fragment都是用于保存Activity的状态,或者借助setTargetFragment来控制其他fragment的UI变化,使用setRetainInstance()这个方法来告诉框架,当配置发生改变的时候,尝试保留这个fragment。

    12.对于Fragment的一些操作对生命周期的影响

    // replace,FragmentA替换为FragmentB,在创建完B以后会先销毁A,再创建B的视图
    FragmentB: onAttach
    FragmentB: onCreate
    ——————————————————————————
    FragmentA: onPause
    FragmentA: onStop
    FragmentA: onDestroyView
    FragmentA: onDestroy
    FragmentA: onDetach
    ——————————————————————————
    FragmentB: onCreateView
    FragmentB: onActivityCreated
    FragmentB: onStart
    FragmentB: onResume

    // add,添加FragmentA
    FragmentA: onAttach
    FragmentA: onCreate
    FragmentA: onCreateView
    FragmentA: onActivityCreated
    FragmentA: onStart
    FragmentA: onResume

    //remove,移除FragmentA
    FragmentA: onPause
    FragmentA: onStop
    FragmentA: onDestroyView
    FragmentA: onDestroy
    FragmentA: onDetach

    //attach,从detach到attach状态
    FragmentA: onCreateView
    FragmentA: onActivityCreated
    FragmentA: onStart
    FragmentA: onResume

    //detach,从attach到detach状态
    FragmentA: onPause
    FragmentA: onStop
    FragmentA: onDestroyView
    注意:hide和show不会触发生命周期回调

    11.fragment生命周期?及案例?

    Fragment必须是依存于Activity而存在的。因此,Activity的生命周期会直接影响到Fragment的生命周期。
    onAttach()
    onCreate()
    onCreateView()
    onActivityCreated()
    onStart()
    onResume()
    onPause()
    onStop()
    onDestroyView()
    onDestroy()
    onDetach()
    注意:除了onCreateView,其他所有的方法如果你重写了,必须要调用父类对于该方法的实现。

    -----
    void onAttach(Context context)//当Activity与Fragment发生关联时调用
    这个方法是在fragment与activity关联之后调用,我们能在这个方法中获取这个关联的activity的实例。

    但是当你的sdk更新到android6.0(api-23)是就会显示这个方法是过时的,使用onAttach(Context context)这个方法代替,但在看fragment的生命周期时,这个方法好像不调用,所以你获取的Context是null
    他只调用一次。

    void onCreate(Bundle savedInstanceState) //fragment初始化的时候调用,
    //通过getActivity() 获取Activity的上下文。
    我们通常在这个方法使用getArgument获取activity传来初始化fragment的参数。
    注意:在这个方法中我们不能获取activity中控件,下面代码是在fragment的onCreate中的,你发现activity不是空,但是text是null。

    因为,这是activity的onCreate还没有执行完,即activity还没有创建完,要想获取activity相关的资源应该在onActivityCreated中获取。
    MainActivity activity=(MainActivity) getActivity();//activity不是null
    TextView text=activity.findViewById(R.id.textview);//text是null

    系统创建fragment的时候回调他,在他里面实例化一些变量,这些个变量主要是:当你暂停 停止的时候,你想保持的数据。
    如果我们要为fragment启动一个后台线程,可以考虑将代码放于此处。
    参数是:Bundle savedInstance, 用于保存Fragment参数,    Fragement也可以重写 onSaveInstanceState(BundleoutState) 方法, 保存Fragement状态;
    可以用于 文件保护 。
    他只调用一次。


    View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
    //创建该Fragment的视图返回Fragment的布局
    主要是通过布局填充器获取fragment布局。通过view.findViewById初始化fragment中的控件,
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view=inflater.inflate(R.layout.text_content, null);
    text=(TextView) view.findViewById(R.id.textview);
    return view;

    第一次使用的时候 fragment会在这上面画一个layout出来,为了可以画控件 要返回一个 布局的view,也可以返回null;
    当系统用到fragment的时候 fragment就要返回他的view,越快越好,所以尽量在这里不要做耗时操作,比如从数据库加载大量数据显示listview,当然线程还是可以的。
    给当前的fragment绘制ui布局,可以使用线程更新UI。说白了就是加载fragment的布局的。
    这里一般都先判断是否为null
    if(text==null){
    Bundle args=getArguments();
    text=args.getString("text");
    }
    if (view == null) {
    view = inflater.inflate(R.layout.hello, null);
    }
    这样进行各判断省得每次都要加载,减少资源消耗。

    当需要创建一个与Fragment关联的View时候会调用,这个方法会返回一个View,这个View会被添加到Activity的View树中,如果你不想Fragment显示一个View就返回null。

    void onActivityCreated(@Nullable Bundle savedInstanceState); //当Activity中的onCreate()方法执行完后调用。
    方法是在activity的onCreate方法执行完执行这个方法,通知fragment,关联的activity的onCreate方法执行完了,即activity创建完了,可以在这个方法中获取activity中的资源。
    例如下面,可以获取activity布局中的TextView控件
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    TextView text=getActivity().findViewById(R.id.textview);//获取activity布局中的TextView控件
    }
    注意了:从这句官方的话可以看出:当执行onActivityCreated()的时候 activity的onCreate才刚完成。
    所以在onActivityCreated()调用之前 activity的onCreate可能还没有完成,所以不能再onCreateView()中进行 与activity有交互的UI操作,UI交互操作可以砸onActivityCreated()里面进行。
    所以呢:这个方法主要是初始化那些你需要你的父Activity或者Fragment的UI已经被完整初始化才能初始化的元素。
    如果在onCreateView里面初始化空间 会慢很多,比如listview等

    void onStart()//在Activity的onStart之后调用,此时Fragement可见;
    是在activity的onstart执行完立即执行,这个方法执行完fragment界面就显示出来,但是现在还没有获取焦点,用户是不能操作。

    void onResume()//在Activity的onResume之后立即执行,此时fragment的获取了界面,用户可以操作。
    Fragment的运行状态,此时Fragment处于运行状态,并且可以与用户之间进行交互;
    在activity中运行是可见的;
    激活, Fragement 进入前台, 可获取焦点时激活;

    void onPause() //执行完后,立即执行activity的onPause方法
    fragment失去焦点,此时用户是不能操作的,执行完立即执行activity的onPause方法。
    和activity一致,其他的activity获得焦点,这个仍然可见,
    第一次调用的时候,指的是用户 离开这个fragment(并不是被销毁),通常用于用户的提交(可能用户离开后不会回来了)。
    有其他Activity获取焦点,前台运行,Fragment所在的Activity失去焦点,部分的显示在前台Activity下面。

    void onStop()//fragment不可见,执行完立即执行activity的onStop方法。
    和activity一致fragment不可见的, 可能情况:activity被stopped了 Or fragment被移除但被加入到回退栈中。
    一个stopped的fragment仍然是活着的,如果长时间不用也会被移除。
    Fragment不再可见,此时的情形可能是Fragment所在的Activity已经stopped了,或者fragment从Activity中移除到Fragment回退栈中。

    一个Stopped状态的Fragment没有被销毁,还在存活状态,它的状态和内部信息被系统记录和保存,只是不可见,不可交互,此时很可能会被系统回收。

    void onDestroyView() ;//与onCreateView相对应,当该Fragment被移除时调用
    在onCreateView中创建的fragment视图会被销毁。Fragment的视图被回收。
    当与Fragment关联的那个View(在onCreatView()方法中创建的)与Fragment解除关联,从View树中移除的时候调用,在下次Fragment需要显示一个View的时候会重新调用onCreatView方法。

    Fragment中的布局被移除时调用。
    表示fragemnt销毁相关联的UI布局,清除所有跟视图相关的资源。
    以前以为这里没什么用处其实 大有文章可做,
    相信大家都用过ViewPager+Fragment,由于ViewPager的缓存机制,每次都会加载3页。
    例如:有四个 fragment 当滑动到第四页的时候,第一页执行onDestroyView(),但没有执行onDestroy。他依然和activity关联。

    当在滑动到第一页的时候又执行了 onCreateView()。 生命周期可以自己试一下。
    那么问题来了。会出现重复加载view的局面,所以这么做;
    @Override
    public void onDestroyView() {
    if(view!=null){
    ((ViewGroup)view.getParent()).removeView(view);
    }
    super.onDestroyView();
    }

    void onDestroy()  //销毁fragment对象,在Activity的onDestroy之前调用;
    当这个fragment不再使用时调用。需要注意的是,它即使经过了onDestroy()阶段,但仍然能从Activity中找到,因为它还没有Detach;

    void onDetach();   //fragment与activity解除关联,fragment的所有的资源都被回收。
    //与onAttach相对应,当Fragment与Activity的关联被取消时调用。


    下面贴一下 activity和fragment同时运行时候的 生命周期?
    开始启动:
    05-07 05:55:08.553: I/Log(1990): oncreate
    05-07 05:55:08.553: I/Log(1990): onAttach_Fragment
    05-07 05:55:08.553: I/Log(1990): onCreate_Fragment
    05-07 05:55:08.553: I/Log(1990): onCreateView_Fragment
    05-07 05:55:08.553: I/Log(1990): onActivityCreated_Fragment
    05-07 05:55:08.553: I/Log(1990): onStart
    05-07 05:55:08.553: I/Log(1990): onStart_Fragment
    05-07 05:55:08.553: I/Log(1990): onResume
    05-07 05:55:08.553: I/Log(1990): onResume_Fragment

    按下home按键
    05-07 05:55:28.725: I/Log(1990): onPause_Fragment
    05-07 05:55:28.725: I/Log(1990): onPause
    05-07 05:55:29.221: I/Log(1990): onStop_Fragment
    05-07 05:55:29.221: I/Log(1990): onStop
    再回到界面
    05-07 05:55:49.441: I/Log(1990): onRestart
    05-07 05:55:49.441: I/Log(1990): onStart
    05-07 05:55:49.441: I/Log(1990): onStart_Fragment
    05-07 05:55:49.441: I/Log(1990): onResume
    05-07 05:55:49.441: I/Log(1990): onResume_Fragment
    销毁activity
    05-07 05:59:02.293: I/Log(1990): onPause_Fragment
    05-07 05:59:02.293: I/Log(1990): onPause
    05-07 05:59:02.757: I/Log(1990): onStop_Fragment
    05-07 05:59:02.757: I/Log(1990): onStop
    05-07 05:59:02.757: I/Log(1990): onDestroyView_Fragment
    05-07 05:59:02.757: I/Log(1990): onDestroy_Fragment
    05-07 05:59:02.757: I/Log(1990): onDetach_Fragment
    05-07 05:59:02.757: I/Log(1990): onDestroy
    可以看出:当显示fragment的时候都先执行activity方法,当销毁的时候都是先执行fragment的方法,这样更好理解fragment是嵌套在activity中。

    三、Fragment生命周期函数的场景演示
    切换到该Fragment
    11-29 14:26:35.095: D/AppListFragment(7649): onAttach
    11-29 14:26:35.095: D/AppListFragment(7649): onCreate
    11-29 14:26:35.095: D/AppListFragment(7649): onCreateView
    11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated
    11-29 14:26:35.120: D/AppListFragment(7649): onStart
    11-29 14:26:35.120: D/AppListFragment(7649): onResume

    屏幕灭掉:
    11-29 14:27:35.185: D/AppListFragment(7649): onPause
    11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState
    11-29 14:27:35.205: D/AppListFragment(7649): onStop

    屏幕解锁
    11-29 14:33:13.240: D/AppListFragment(7649): onStart
    11-29 14:33:13.275: D/AppListFragment(7649): onResume

    切换到其他Fragment:
    11-29 14:33:33.655: D/AppListFragment(7649): onPause
    11-29 14:33:33.655: D/AppListFragment(7649): onStop
    11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView

    切换回本身的Fragment:
    11-29 14:33:55.820: D/AppListFragment(7649): onCreateView
    11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated
    11-29 14:33:55.825: D/AppListFragment(7649): onStart
    11-29 14:33:55.825: D/AppListFragment(7649): onResume

    回到桌面
    11-29 14:34:26.590: D/AppListFragment(7649): onPause
    11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState
    11-29 14:34:26.880: D/AppListFragment(7649): onStop

    回到应用
    11-29 14:36:51.940: D/AppListFragment(7649): onStart
    11-29 14:36:51.940: D/AppListFragment(7649): onResume

    退出应用
    11-29 14:37:03.020: D/AppListFragment(7649): onPause
    11-29 14:37:03.155: D/AppListFragment(7649): onStop
    11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView
    11-29 14:37:03.165: D/AppListFragment(7649): onDestroy
    11-29 14:37:03.165: D/AppListFragment(7649): onDetach

  • 相关阅读:
    CGContextRef使用简要教程
    使用JSONObject 深度序列化和反序列化
    使用yum方式在centOS上安装mysql
    安全驾驶技巧
    java -jar xxx.jar
    [转帖]鲍鹏山:我们培养了很多高学历的野蛮人
    perl的几个小tips
    上传项目至svn服务器,从svn上获取项目
    UE把环境变量Path改了
    成就连自己都惊讶的未来
  • 原文地址:https://www.cnblogs.com/awkflf11/p/9175510.html
Copyright © 2011-2022 走看看