fragment懒加载

  今天在github上看了一些tablayout的类库,如FlycoTabLayoutSmartTabLayout等,都是star比较靠前的类库。

1
public void setTabData(ArrayList<CustomTabEntity> tabEntitys, FragmentManager fm, int containerViewId, ArrayList<Fragment> fragments)

像这个是FlycoTabLayout的设置tab数据的方法,里面直接传了一个fragment的集合,说明这些集合里的framgment对象都是先new出来的,然后再放到一个集合中作为参数传到了setTabData方法中,若我们没有对这些framgent页面做处理,相当于当我们加载了第一个fragment时,也就相当于加载了其他的fragment界面了,但是,现在大部分的app,并不希望你进到主页后,就将其他的framgment都加载好了,而是当你第一次点击其他的fragment页面时,才去加载网络拉取数据,这便是我们所说的懒加载(网上很多人称为Fragment的最优加载)。一般我们会fragment结合viewpager使用,viewpager通常会有预加载机制,默认情况下会先加载左右一页的数据,所以想要等待页面可见的时候再去加载网络数据,那么fragment的懒加载是必不可少的解决方案。

  那么该怎么实现呢,就在于要重写Framgent类的一个方法setUserVisibleHint(boolean isVisibleToUser),这个方法字面意思就是设置用户可见隐藏,里面传一个boolean类型的参数——表示当前界面可见或者不可见,这个方法在Fragment界面切换到可见或者不可见的时候调用,其次我们希望对每一个Framgent都这样处理,所以我们将其写在BaseFragment中,先上代码。
  大坑:虽然这个方法是如此,并且官方也给出了解释,但是如果你只是几个framgent的切换,并没有使用到viewpager,该方法是并不会调用的,今天也测试了确实是如此。只有当你结合viewpager使用时,fragment的切换才会调用该方法

1
2
* @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
* false if it is not.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public abstract class BaseFragment extends Fragment {
protected boolean isViewInitiated; //view是否加载,默认false
protected boolean isVisibleToUser; //是否用户可见,默认false
protected boolean isDataInitiated; //数据是否加载,默认false
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//view加载成功
isViewInitiated = true;
//准备加载数据
prepareFetchData();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
//准备加载数据
prepareFetchData();
}
//加载数据,抽象方法,具体子类实现
public abstract void fetchData();
public void prepareFetchData() {
//判断如果用户可见,view加载成功,数据未加载
if (isVisibleToUser && isViewInitiated && !isDataInitiated) {
//加载数据
fetchData();
//数据加载成功
isDataInitiated = true;
}
}
}

  1.在onActivityCreated()方法中(该方法在Activity的onCreate()方法之前调用,可以获取除了View之外的资源,并且在Framgent的onCreate(),onCreateView()方法之后调用,所以调用该方法时,view已加载成功)

1
2
3
4
5
6
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitiated = true; //view加载成功
prepareFetchData();//预加载数据
}

  2.在prepareFetchData()方法中

1
2
3
4
5
6
7
8
9
10
11
public boolean prepareFetchData() {
//如果页面可见且view加载成功且数据还未加载
if (isVisibleToUser && isViewInitiated && !isDataInitiated) {
//若以上三者条件都满足,则开始加载数据
fetchData();
//数据加载成功标志
isDataInitiated = true;
return true;
}
return false;
}

  3.在第一次调用onActivityCreated()方法,此时isViewInitiated为true,表示view已加载,但是只满足了两个条件(view加载完成,数据未加载),但是要知道setUserVisibleHint()方法是在fragment页面切换的时候才调用的,所以当页面切换时,isVisibleToUser才为true,这时再调用prepareFetchData()方法,三个条件都满足,调用fetchData()方法,该方法我们设置为抽象,子类实现该方法真正加载数据。

1
public abstract void fetchData();

  到此,就是framgent的懒加载的实现,也许这也是对立的,当存在预加载时,就可以使用懒加载来处理数据加载。