Android Fragment
yunshuipiao opened this issue · 0 comments
Android Fragment
这篇文章讲解 Fragment 的基本概念使用。
基础概念
因为support库是不断更新的,因此建议使用support库中的android.support.v4.app.Fragment,而不要用系统自带的android.app.Fragment。
而如果要使用support库的Fragment,Activity必须要继承FragmentActivity(AppCompatActivity是FragmentActivity的子类)
。
根据官方的定义:
- framgent 依赖于 Activity,不能独立存在
- 一个 Activity 中可以有多个 Fragment
- 一个 Fragment 可以被多个 Activity 重用。
- Fragment 有自己的生命周期,并能接收输入事件
- 可以在 Activity 运行时动态的添加和删除 Fragment。
其优势在于:
-
模块化:逻辑放在 Fragment 中,Activity 管理和同步 Fragment 之间的信息
-
可重用:多个 Activity 可以重用一个 Fragment 。
-
可适配:根据硬件的屏幕尺寸,屏幕等可以实现不同的布局。
Fragment 的核心类
- Fragment:基类,任何创建 Fragment 都需要继承该类
- FragmentManager:管理和维护 Fragment, 也是抽象类,具体的实现类是 FragmentManagerImpl。
- FragmentTransaction:对 Fragment 的添加,删除等操作都需要通过事务方式进行,也是抽象类,其实现类是 BackStackRecord。
如果在创建 Fragment时要传入参数,必须通过 setArguments() 方式添加,而不建议通过 Fragment 添加带参数的构造函数。因为 通过前者方式添加,在由于内存紧张导致 Fragment 被系统杀死并恢复时可以保留这些数据。在Fragment的 onAttach() 中通过 getArguments() 获得传进来的参数,并在之后使用这些参数。
onSaveInstanceState()
是当activity
有可能被
系统回收的情况下,而且是在onStop()之前。注意是有可能
,如果是已经确定会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。或者也可以说,此方法只有在activity被异常终止的情况下会被调用
。
onRestoreInstanceState(Bundle savedInstanceState)
只有在activity确实
是被系统回收,重新创建activity
情况下才会被调用,并且是在onStart()之后,onResume()之前的。
懒加载
懒加载主要用于ViewPager且每页是Fragment的情况,场景为微信主界面,底部有4个tab,当滑到另一个tab时,先显示”正在加载”,过一会才会显示正常界面。
默认情况,ViewPager会缓存当前页和左右相邻的界面。实现懒加载的主要原因是:用户没进入的界面需要有一系列的网络、数据库等耗资源、耗时的操作,预先做这些数据加载是不必要的。
这里懒加载的实现思路是:用户不可见的界面,只初始化UI,但是不会做任何数据加载。等滑到该页,才会异步做数据加载并更新UI。
懒加载主要依赖Fragment的setUserVisibleHint(boolean isVisible)
方法,当Fragment变为可见时,会调用setUserVisibleHint(true)
;当Fragment变为不可见时,会调用setUserVisibleHint(false)
,且该方法调用时机:
onAttach()
之前,调用setUserVisibleHint(false)。onCreateView()
之前,如果该界面为当前页,则调用setUserVisibleHint(true),否则调用setUserVisibleHint(false)。- 界面变为可见时,调用
setUserVisibleHint(true)
。 - 界面变为不可见时,调用
setUserVisibleHint(false)
。
commitAllowingStateLoss
使用Fragment的时候偶尔会有这么一个报错,Can not perform this action after onSaveInstanceState,意思为无法再onSaveInstanceState之后执行该操作,这个操作就是指commit()。
为什么我们会有这种报错呢?
因为我们在使用add(),remove(),replace()等方法将Fragment的变化添加进去,然后在通过commit去提交这些变化(另外,在commit之前可以去调用addToBackState()方法,将这些变化加入到activity管理的back stack中去,这样用户调用返回键就可以回退这些变化了),提交完成之后这些变化就会应用到我们的Fragment中去。但是,这个commit()方法,你只能在avtivity存储他的状态之前调用,也就是onSaveInstanceState()。
activity有一个保存状态的方法和恢复状态的方法。
在onSaveInstanceState()方法之后去调用commit(),就会抛出我们遇到的这个异常,这是因为在onSaveInstanceState()之后调用commit()方法,这些变化就不会被activity存储,即这些状态会被丢失,但我们可以去用commitAllowingStateLoss()这个方法去代替commit()来解决这个问题。