fragment 的懒加载
- 懒加载
什么是懒加载:
只有在 fragment 显示在界面的时候,才进行数据的加载
懒加载类别:
不同 fragment 的添加方式,需要采用不同的懒加载处理方法
fragment 添加方式:
- replace()
- add()/hide()/show()
- viewpager + fragment
replace()
/**
* 以replace()的方式添加fragment到指定布局R.id.layout_fragment
*/
private void showFragment(Fragment fragment) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.layout_fragment, fragment);
transaction.commit();
}
每次均是添加新的 fragment 实例,数据需要重新加载
选择合适的生命周期即可
add()/hide()/show()
/**
* 以add()/hide()/show()的方式添加
* 判断fragment是否已被添加进入fragmentManager
* 已添加:直接显示
* 未添加:指定布局R.id.layout_content,add
*/
private void showFragment(Fragment newFragmeent) {
if (newFragmeent != currentFrament ) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (!newFragmeent.isAdded()) {
transaction
.hide(currentFrament)
.add(R.id.layout_content, newFragmeent)
.commit();
} else {
transaction
.hide(currentFrament)
.show(newFragmeent)
.commit();
}
currentFrament = newFragmeent
}
}
- fragment 未被添加进入 fragmentManager,采用 add 的方式添加 :
触发生命周期 与 replace()的处理方式相同,选择合适生命周期即可
- fragment 已被添加进入 fragmentManager,采用 show 的方式:
触发 onHiddenChanged(boolean hidden) 一般无需处理加载,数据已经在 add()时通过生命周期加载过了
/**
* show()/hide()会触发 add()不会触发
* 此方法只是用于感知show()和hide()
*/
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(hidden){
//TODO now invisible to user
} else {
//TODO now visible to user
}
}
viewpager + fragment
- 只有在 adapter 是 FragmentPagerAdapter 或 FragmentStatePagerAdapter 才有效果
需要注意的是:
位于 FragmentPagerAdapter 或 FragmentStatePagerAdapter 当中的fragment,setUserVisibleHint(boolean isVisibleToUser)的调用时机分为两种
- fragment 实例化 : 所有生命周期之前
- fragment 只是切换显隐,但并未实例化 : 显示或隐藏的时候
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHasCreatedView = false;
mHasLoadedOnce = false;
isFragmentVisible = false;
}
/**
* 两步分别处理两个fragment
* 1. 由不可见切换为可见的fragment
* 2. 由可见切换为不可见的fragment
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//通过mRootView是否为null来判断是否已经初始化完成(也就是判断具体是通过哪一次触发)
if (mRootView == null) {
return;
}
//初始化完成,标记,代表是由第二种方式触发
mHasCreatedView = true;
//isVisibleToUser == true,表示fragment由不可见切换为可见
if (isVisibleToUser) {
onFragmentVisibleChange(true);
isFragmentVisible = true;
changeToVisiable();
return;
}
//可见的fragment由可见切换为不可见
if (isFragmentVisible) {
onFragmentVisibleChange(false);
isFragmentVisible = false;
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
...
//通过第一种方式触发时,并没有进行加载数据
if (mHasCreatedView){
return;
}
//进行第一种方式触发时的数据加载
if (getUserVisibleHint()) {
onFragmentVisibleChange(true);
isFragmentVisible = true;
changeToVisiable();
}
}
private void changeToVisiable(){
//从未加载过,则加载
if (!mHasLoadedOnce) {
onLazyLoad();
}
}
/**
* 可见性的切换触发
*
*/
protected void onFragmentVisibleChange(boolean isvisible) {
}
/**
* 懒加载
*/
protected void onLazyLoad() {
//已经加载过,标记
mHasLoadedOnce = true;
}