ViewPager在设计的时候有一个预加载的机制,也就是如果你处于当前这个page界面时,会预先加载下一个page。但是有的时候设计到网络请求,就需要取消掉这个预加载。

setOffscreenPageLimit()这一个方法是设置预加载的个数,默认为1,但是当你设置为0的时候也会强行将它设置为1。

1
2
3
4
5
6
7
8
9
10
11
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}

所以说,第一种取消预加载的方法就出来了,那就是需要更改这个DEFAULT_OFFSCREEN_PAGES = 0,但是需要更改jar包,特别麻烦,所以接下来就用一下第二种方法

从官方的API文档来看,Fragment中有一个方法,这个方法是执行在onCreateView()方法之前的,叫做setUserVisibleHint()。用来告诉系统这个UI是否可见。

1
2
3
4
Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
An app may set this to false to indicate that the fragment's UI is scrolled out of visibility or is otherwise not directly visible to the user. This may be used by the system to prioritize operations such as fragment lifecycle updates or loader ordering behavior.
Parameters
isVisibleToUser true if this fragment's UI is currently visible to the user (default), false if it is not.

所以第二种方法就是重写这个setUserVisibleHint
首先,创建一个父类,以后的Fragment都继承自MyFragment,在其中定义一个抽象方法,在子类中实现延迟加载的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class MyFragment extends Fragment {

protected boolean isVisible;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
isVisible = true;
delayLoad();
} else {
isVisible = false;
}
}

protected abstract void delayLoad();
}

下面的就是在子类中如何实现延迟加载,同时还引入了布局的复用,因为每次切换都会产生View的重绘,浪费资源

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
private boolean isReady = false;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

if (rootView == null) {

rootView = inflater.inflate(R.layout.viewpager_printpage, container, false);
isReady = true;
delayLoad();
Log.d("info", "onCreateView");
} else {
Log.d("info", "rootView != null");
}

// Cache rootView.
// remove rootView from its parent
ViewGroup parent = (ViewGroup) rootView.getParent();
if (parent != null) {
parent.removeView(rootView);
}
return rootView;
}

@Override
protected void delayLoad() {
if (!isReady || !isVisible) {
return;
}

// This is a random widget, it will be instantiation in init()
if (myViewPager_Printpage == null) {
init();
}
}