使用Fragment 官方例子中显示:

例如:一个学生Fragment,需要传入studentId,进行http请求显示,那么setArguments后防止杀掉Fragment后,参数为0,显示不了数据。

1 public static StudentFragment newInstance(int studentId){
2         StudentFragment fragment = new StudentFragment();
3         Bundle bundle = new Bundle();
4         bundle.putInt("student_id",  studentId);
5         fragment.setArguments(bundle);
6         return fragment;
7     }

setArguments:

1 private int mStudentId = 0;
2
3 @Override
4     public void setArguments(Bundle args) {
5         super.setArguments(args);
6
7         mStudentId = args.getInt("student_id", 0);
8     }

那么app在杀死后,回到这个Fragment 时,会在onCreateView时,进行获取参数,获取正确的页面数据,不然有可能会因为null,而崩毁。

@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mStudentId = getArguments().getInt("student_id", 0);return super.onCreateView(inflater, container, savedInstanceState);}

我为什么不主张使用Fragment

Fragment:( Fragment就相当于一个有生命周期的View,它的生命周期被所在的Activity的生命周期管理 )

生命周期回调说明:

onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用

与Activity 依赖关系:

与ViewPager 的关系:

(1)setOffscreenPageLimit

1 // 预加载页面的数量
2 viewPager.setOffscreenPageLimit(2);

知道ViewPager会有预加载的特性,我以为Fragment_1会从 1 onAttach() 开始直到 6 onResume()后,Fragment_2才会开始从 1onAttach()开始,到了3 onCreateView()会停止。然而,并不是预想的这样。

首先,Fragment_1 经历 1_onAttach() 和 2_onCreate() 后, Fragment_2也开始走了 1_onAttach()和 2_onCreate()方法。

接着,Fragment_1依次经历 3_onCreateView(), 4_onCreateActivity(),5 _onStart ,6_onResume()。此时,Fragment_1获得焦点,已经展示在手机屏幕。Fragment_2也接着从 3_onCreate()开始直到也执行到 6_onResume()方法。疑问就在这,我个人感觉既然Fragment_2没有在屏幕显示,就不会执行到 6_onResume()方法,然而Log信息却显示执行到了 6_onResume()。这里记录一下。

多了Fragment_3的Log信息,而且走的方法和Frgment_1和2是一样的。后面的情况的Log信息便不再贴出来了,本质是一样的,只是多预加载了一个Fragment。但此时ViewPager依然只是保留3个Fragment的信息。当滑到Fragment_4的时候,Fragment_1走了7_onPause(),8_onStop(),9_onDestroyView()。Fragment_2,3,4则处于6_onResume()。

这个方法对Fragment生命周期方法的调用顺序上并没有什么影响,只是预加载的Fragment的数量又设置的limit参数决定。

(2)setUserVisibleHint

setUserVisibleHint()这个方法会在预加载Fragment时,会在Fragment的1_onAttach()前调用。此时,在setUserVisibleHint()里面调用也不用害怕空指针的问题,因为有3个前条件。当通过滑动ViewPger时,根据6.1知道,每次滑动都会调用setUserVisibleHint()这个方法,进行预加载后,当滑到Fragment_2,3,4时,就会调用里面的load()方法。

在Fragment的4_onCreateActivity()中调用load。我个人习惯把网络请求放在这个生命周期。在Fragment_1和点击Tab时,引起问题的原因就是setUserVisibleHint()先于1_onAttach()调用,不能满足前提条件中的isCreate,所以load方法不会被调用。而4_onCreateActivity()中会再次调用load()方法,此时还满足3个前提条件。这样,遗留的问题也解决了。ViewPager中Fragment延迟加载这个需求也可以实现了。如果此时Fragment中有一个轮播图的话,也可以通过getUserVisibleHint()这个方法来选择关闭轮播图线程的时机。

Fragment Api:

Fragment常用的三个类:

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

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性

主要的操作都是FragmentTransaction的方法:

 1 // v4包中,getSupportFragmentManager
 2 FragmentManager fm = getFragmentManager();
 3 // 开启一个事务 (主要的操作都是FragmentTransaction的方法)
 4 FragmentTransaction transaction = fm.benginTransatcion();
 5
 6 // 往Activity中添加一个Fragment
 7 transaction.add(Fragment fragment);
 8 // 从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。
 9 transaction.remove(Fragment fragment);
10 // 使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体
11 transaction.replace(R.id.XXX, Fragment fragment);
12 // 隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
13 transaction.hide(Fragment fragment);
14 // 显示之前隐藏的Fragment
15 transaction.show(Fragment fragment);
16 //提交一个事务
17 transatcion.commit();

// 会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。

detach()

// 重建view视图,附加到UI上并显示。

attach();

判断什么时候该使用什么方法:

(1)希望保留用户操作的面板,可以使用hide和show。

(2)不希望保留用户操作,可以使用remove(),然后add();或者直接使用replace(),效果相同。

(3)remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。

(4)当前Activity一直存在,那么在不希望保留用户操作的时候,可以优先使用detach。

参考地址:Android Fragment 真正的完全解析(上)     Android Fragment 真正的完全解析(下)

对于用法:

(1)getActivity() 方法空指针问题:

在Fragment基类里设置一个Activity mActivity的全局变量,在onAttach(Activity activity)里赋值,使用mActivity代替getActivity(),保证Fragment即使在onDetach后,仍持有Activity的引用(有引起内存泄露的风险,但是异步任务没停止的情况下,本身就可能已内存泄漏,相比Crash,这种做法“安全”些),即:
protected Activity mActivity;/**
* API低于 23 的版本中不会去调用后者,只会去调用onAttach(Activity)
*/
@Override
public void onAttach(Activity activity) {super.onAttach(activity);this.mActivity = activity;
}/**
*  如果用了support 23的库,上面的方法会提示过时,且不会被调用,可以用下面的方法代替
*/
@Override
public void onAttach(Context context) {super.onAttach(context);this.mActivity = (Activity) context;
}

如不需要使用getActivity():

 1    /*
 2     * onAttach(Context) is not called on pre API 23 versions of Android and onAttach(Activity) is deprecated
 3     * Use onAttachToContext instead
 4     */
 5    @TargetApi(23)
 6    @Override
 7    public void onAttach(Context context) {
 8        super.onAttach(context);
 9        onAttachToContext(context);
10    }
11
12    /*
13     * Deprecated on API 23
14     * Use onAttachToContext instead
15     */
16    @SuppressWarnings("deprecation")
17    @Override
18    public void onAttach(Activity activity) {
19        super.onAttach(activity);
20        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
21            onAttachToContext(activity);
22        }
23    }
24
25    /*
26     * Called when the fragment attaches to the context
27     */
28    protected void onAttachToContext(Context context) {
29       //do something
30    } 

(2)未必靠谱的出栈方法remove()

如果你想让某一个Fragment出栈,使用remove()在加入回退栈时并不靠谱。

如果你在add的同时将Fragment加入回退栈:addToBackStack(name)的情况下,它并不能真正将Fragment从栈内移除,如果你在2秒后(确保Fragment事务已经完成)打印getSupportFragmentManager().getFragments(),会发现该Fragment依然存在,并且依然可以返回到被remove的Fragment,而且是空白页面。

如果你没有将Fragment加入回退栈,remove方法可以正常出栈。

如果你加入了回退栈,popBackStack()系列方法才能真正出栈,这也就引入下一个深坑,popBackStack(String tag,int flags)等系列方法的BUG。

(3)Fragment转场动画

如果你的Fragment没有转场动画,或者使用setCustomAnimations(enter, exit)的话。

1 getFragmentManager().beginTransaction().setCustomAnimations(enter, exit);
3  // 如果通过tag/id同时出栈多个Fragment的情况时,
4  // 请谨慎使用.setCustomAnimations(enter, exit, popEnter, popExit)
5  // 在support-25.4.0之前出栈多Fragment时,伴随出栈动画,会在某些情况下发生异常
6  // 你需要搭配Fragment的onCreateAnimation()临时取消出栈动画,或者延迟一个动画时间再执行一次上面提到的Hack方法,排序

注意:如果你想给下一个Fragment设置进栈动画和出栈动画,.setCustomAnimations(enter, exit)只能设置进栈动画,第二个参数并不是设置出栈动画;
请使用.setCustomAnimations(enter, exit, popEnter, popExit),这个方法的第1个参数对应进栈动画,第4个参数对应出栈动画,所以是.setCustomAnimations(进栈动画, exit, popEnter, 出栈动画)

如果想让出栈动画运作正常的话,需要使用Fragment的onCreateAnimation中控制动画:

1 @Override
2 public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
3     // 此处设置动画
4 }

pop多个Fragment时转场动画 带来的问题:

在使用 pop(tag/id)出栈多个Fragment的这种情况下,将转场动画临时取消或者延迟一个动画的时间再去执行其他事务;

原因在于这种情景下,可能会导致栈内顺序错乱(上文有提到),同时如果发生“内存重启”后,因为Fragment转场动画没结束时再执行其他方法,会导致Fragment状态不会被FragmentManager正常保存下来。

2、进入新的Fragment并立刻关闭当前Fragment 时的一些问题
(1)如果你想从当前Fragment进入一个新的Fragment,并且同时要关闭当前Fragment。由于数据结构是栈,所以正确做法是先pop,再add,但是转场动画会有覆盖的不正常现象,你需要特殊处理,不然会闪屏!

如果你遇到Fragment的mNextAnim空指针的异常(通常是在你的Fragment被重启的情况下),那么你首先需要检查是否操作的Fragment是否为null;其次在你的Fragment转场动画还没结束时,你是否就执行了其他事务等方法;解决思路就是延迟一个动画时间再执行事务,或者临时将该Fragment设为无动画

对于一些操作,Fragment发生的生命周期变化:

切换到该Fragment:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume()

屏幕灭掉或者回到桌面(Home): onPause() -> onSaveInstanceState() -> onStop()

屏幕解锁或者重新回到应用: onStart() -> onResume()

切换到其他Fragment: onPause() -> onStop() -> onDestroyView()

切换回本身的Fragment: onCreateView() -> onActivityCreated() -> onStart() -> onResume()

退出应用:onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach()

参考:

Fragment全解析系列(一):那些年踩过的坑

转载于:https://www.cnblogs.com/CharlesGrant/p/4876135.html

Android Fragment 生命周期及其正确使用(建议使用自定义View替换Fragment)相关推荐

  1. Android Acitivity 生命周期

    Fragment 的生命周期: Android Fragment 生命周期及其API使用(建议使用自定义View替换Fragment) Activity的生命周期: (1)启动Activity:系统会 ...

  2. Android:Fragment生命周期(结合Activity的生命周期进行分析)

    文章目录 前言 一.Fragment生命周期概述 启动 退出 二.Fragment生命周期细述 1.onCreate(Bundle) 2.onCreateView(LayoutInflater, Vi ...

  3. Fragment生命周期详解

    关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Frag ...

  4. Android零基础入门第86节:探究Fragment生命周期

    2019独角兽企业重金招聘Python工程师标准>>> 一个Activity可以同时组合多个Fragment,一个Fragment也可被多个Activity 复用.Fragment可 ...

  5. android fragment 生命周期

    今天,简单讲讲fragment 的生命周期. 其实,对于fragment ,大家都很熟悉.我也经常使用,但是最近做一个功能时,在activity里面调用fragment 的函数,发现变量居然没有初始化 ...

  6. Android中Fragment生命周期和基本用法

    1.基本概念 1. Fragment是什么? Fragment是可以让你的app纵享丝滑的设计,如果你的app想在现在基础上性能大幅度提高,并且占用内存降低,同样的界面Activity占用内存比Fra ...

  7. android屏幕旋转生命周期,Activity、Fragment生命周期---横竖屏切换的生命周期

    先贴出一张大家众所周知activity流程图 onCreate():创建Activity调用,用于Activity的初始化,还有个Bundle类型的参数,可以访问以前存储的状态.onStart():A ...

  8. android fragment生命周期图,Fragment生命周期详解

    序言 Fragment从Android v3.0版本开始引入的,随着界面布局的复杂化,处理起来也更加的复杂,引入Fragment可以把Activity拆分成多个部分.一个Activity可以同时组合多 ...

  9. android viewpager fragment 生命周期,ViewPager中Fragment的生命周期

    网上有很多Fragment生命周期的帖子,但是看了一下,没有找到自己想了解的东西,于是决定自己动手体验一下这个生命周期.主要想了解以下几个问题: Activity中的Fragment的生命周期 Vie ...

最新文章

  1. 是否能领先e步 浅析SSD中的eTLC和eMLC颗粒
  2. 021 设计模式之工厂方法模式,抽象工厂模式的区别
  3. 如何在PowerPoint中自动调整图片大小
  4. c语言打砖块游戏代码,打砖块游戏的源代码(请多指教)
  5. Python3.6 IDLE 使用 multiprocessing.Process 不显示执行函数的打印
  6. 谈谈我对MYSQL乱码的解决办法
  7. L323 英语有必要学语法吗
  8. Remoting压缩信道的编程配置方式
  9. 坐高铁只能用身份证了?
  10. C++指针delete后赋值为NULL的一些问题
  11. 电子技术网站大全[转]
  12. Sematic-UI安装方法:
  13. 看完就会flink基础API
  14. ReviewBoard 的安装和使用(二)—— 邮箱的配置
  15. 获取MP3音频时长 | Java工具类
  16. 【手机刷机】360 n4s降级039 root刷机(卡刷、线刷等)
  17. 【数据结构】栈的应用-算术表达式求值#数据结构实验任务书
  18. TreeView添加treeView1_NodeMouseClick----多么痛的领悟。。。
  19. 15个Python入门小程序,同事准时下班“小技巧”被我发现了
  20. u盘无法linux,Linux 3.18U盘无法正确使用

热门文章

  1. 关于JSON CSRF的一些思考
  2. 《数据库SQL实战》查找所有员工的last_name和first_name以及对应的dept_name
  3. 大数据hadoop资源网址
  4. 当不能用for等循环时,可以考虑递归
  5. 【搜索引擎基础知识3】搜索引擎相关开源项目及网站
  6. AdapterView及其子类之一:基本原理(ListView、ListActivity类型)
  7. 思维模型篇:数据分析必知必会的两个原则
  8. 第06课:动手实战基于 ML 的中文短文本分类
  9. 聊聊高并发(二十四)解析java.util.concurrent各个组件(六) 深入理解AQS(四)
  10. Web 应用程序的自动化测试