Fragment懒加载

2,194 阅读3分钟

前言

  1. 为什么要对Fragment使用懒加载?

在项目中,使用Fragment的时候,往往是和ViewPager一起使用,而ViewPager有默认的加载机制,会预加载当前页的前后两个页面(执行onResume方法),如果几个页面都有数据操作的逻辑,比如加载网络数据,即使是不可见的页面也会加载数据,竞争网络流量,这样会造成一定的资源浪费,所以会用到懒加载。

  1. 什么是懒加载?

在很多地方都用到这个概念,比如懒加载单例模式,就是在使用时才会加载,如果一直不使用就一直不加载。

由于Fragment提供的setUserVisibleHint(boolean isVisibleToUser)已经标记位@Deprecated,转而使用setMaxLifecycle方法,今天讲一下使用setMaxLifecycle方法实现Fragment的懒加载。

介绍

FragmentTransaction

setMaxLifecycle方法位于FragmentTransaction类中,内容如下:

@NonNull
public FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment,
    @NonNull Lifecycle.State state) {
    addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state));
    return this;
}

其中包含两个参数:

  • fragment:需要操作的Fragment实例
  • state:状态,Lifecycle.State枚举类型,包含5个状态

Lifecycle.State的状态:

  • INITIALIZED:初始化完成状态,Fragment已经构建完成,未调用到onCreate;
  • CREATED:创建完成状态,在onCreate方法之后,onStop之前;
  • STARTED:在onStart方法之后,onPause之前;
  • RESUMED:在onResume方法之后;
  • DESTROYED:在onDestroyed方法之后。

setMaxLifecycle可直接解释为:设置Fragment所处的最大声明周期。如果Fragment超过了当前设置的最大周期值,会将Fragment降到设置的值。

各个状态对应可执行到的生命周期如下:

  • INITIALIZED:无法设置此方法,Cannot set maximum Lifecycle below CREATED;
  • CREATED:onAttach -> onCreate;
  • STARTED:onAttach -> onCreate -> onCreateView ;
  • RESUMED:onAttach -> onCreate -> onCreateView -> onActivityCreated -> onStart -> onResume;
  • DESTROYED:无法设置此方法,Cannot set maximum Lifecycle below CREATED。

其实对我们可以说使用的只有中间3种,看一下如何使用。

使用

1.初始化

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.layout_fragment, mFragment);
fragmentTransaction.setMaxLifecycle(mKingFragment, Lifecycle.State.CREATED);
fragmentTransaction.commit();

通过这个方法,让Fragment添加时的生命周期执行到onCreate。

很明显可以看出,如果使用懒加载时,可以将非前端显示的Fragment设置到如下状态,将加载数据的方法写到onCreate之后的生命周期内,如需加载数据,再通过下面的方法将最大值往后跳转。

2.更新

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setMaxLifecycle(mFragment, Lifecycle.State.RESUMED);
fragmentTransaction.commit();

通过这个方法,可以让Fragment执行 onCreateView -> onActivityCreated -> onStart -> onResume。

更新方法只能自上而下的改变状态:CREATED -> STARTED -> RESUMED,否则不会响应,而生命周期回调也会随着状态的更新而顺序调用下去。

FragmentPagerAdapter

在ViewPager+Fragment的场景中,FragmentPagerAdapter也做了响应的适配。

源码中默认的构造方法已经弃用,转而使用需要提供Behaviour参数的构造方法

@Deprecated
public FragmentPagerAdapter(@NonNull FragmentManager fm) {
    this(fm, BEHAVIOR_SET_USER_VISIBLE_HINT);
}
​
public FragmentPagerAdapter(@NonNull FragmentManager fm,
            @Behavior int behavior) {
    mFragmentManager = fm;
    mBehavior = behavior;
}

Behavior只有一个值可以提供了,因为另一个值也弃用了。也就是说FragmentPagerAdapter默认提供了懒加载,注释中已经解释。

@Deprecated
public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;
​
/**
* Indicates that only the current fragment will be in the Lifecycle.State.RESUMED state. All other Fragments are capped at Lifecycle.State.STARTED.
*/
public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;

所以ViewPager+Fragment简单实现如下:

//初始化新建的Fragment,添加入list中
List<Fragment> fragmentList = new ArrayList<>(2);
fragmentList.add(new Fragment1());
fragmentList.add(new Fragment2());
​
//获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();
​
//初始化FragmentAdapter,提供参数FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
MyFragmentAdapter adapter = new MyFragmentAdapter(fragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, fragmentList);
​
//在layout中的viewpager
ViewPager viewPager = findViewById(R.id.vp_root);
viewPager.setAdapter(adapter);

总结:

本节内容很简单,通过setMaxLifecycle可以设置Fragment的生命周期最大值,如果需要懒加载,可以先将最大值设置为靠前,而在后面调用的生命周期回调中实现加载数据的方法。

ViewPager+Fragment默认提供了懒加载,使用FragmentPagerAdapter即可。