ViewPager+Fragment的模式再常见不过了,以国民应用微信为例,假设微信也是ViewPager+Fragment的实现方式,那表现形式上就是一个ViewPager管理了四个Fragment,左右滑动来回切换。但是ViewPager有一个奇葩的特性叫:预加载,比如打开微信,首先看到的是第一个Tab(微信),但事实上第二个Tab(通讯录)已经加载好了。当选择第二个Tab(通讯录),第三个Tab(发现)已经加载好了,以此类推。
但上述ViewPager+Fragment的这种组合并不完美,因为我希望用户选择了哪个Tab再去加载哪个Tab的数据,而不要去做预加载,假如当前页面和预加载页面都有大量的网络请求,可能就会比较慢,有很多请求在排队。关于这个问题,也有很偏激的做法,比如弃用ViewPager,自己手动管理Fragment,或者直接禁掉ViewPager预加载。有一种比较合适的方案是保持ViewPager预加载的特性,但是只初始化View,选择当前Tab的时候再进行网络请求。关于这一方案的实现,也是众说纷纭,千奇百怪。最后,还是选择男神Stay的方案。
直接上代码。
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
BasePageFragment
extends
Fragment
{
protected
boolean
isViewInitiated
;
protected
boolean
isVisibleToUser
;
protected
boolean
isDataInitiated
;
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
}
@Override
public
void
onActivityCreated
(
Bundle
savedInstanceState
)
{
super
.
onActivityCreated
(
savedInstanceState
)
;
isViewInitiated
=
true
;
prepareFetchData
(
)
;
}
@Override
public
void
setUserVisibleHint
(
boolean
isVisibleToUser
)
{
super
.
setUserVisibleHint
(
isVisibleToUser
)
;
this
.
isVisibleToUser
=
isVisibleToUser
;
prepareFetchData
(
)
;
}
public
abstract
void
fetchData
(
)
;
public
boolean
prepareFetchData
(
)
{
return
prepareFetchData
(
false
)
;
}
public
boolean
prepareFetchData
(
boolean
forceUpdate
)
{
if
(
isVisibleToUser
&&
isViewInitiated
&&
(
!
isDataInitiated
||
forceUpdate
)
)
{
fetchData
(
)
;
isDataInitiated
=
true
;
return
true
;
}
return
false
;
}
}
|
这是一个父类,看代码这里只有一个setUserVisibleHint需要说下,这是一个相当生僻的方法,我们可以用这个方法来判断当前UI是否可见,所以在prepareFetchData方法里我们做如下判断:就是当前UI可见,并且fragment已经初始化完毕,如果网络数据未加载,那么请求数据,或者需要强制刷新页面,那么也去请求数据,So easy。子Fragment只需要继承父类,实现抽象方法,在fetchData()里做网络请求或者其他耗时操作即可。再在写个子类吧。
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
class
PageFragment
extends
BasePageFragment
{
public
static
PageFragment
newInstance
(
String
title
)
{
PageFragment
fragment
=
new
PageFragment
(
)
;
Bundle
args
=
new
Bundle
(
)
;
args
.
putString
(
"key_fragment_title"
,
title
)
;
fragment
.
setArguments
(
args
)
;
return
fragment
;
}
private
String
title
;
private
TextView
tv
;
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
)
;
title
=
getArguments
(
)
.
getString
(
"key_fragment_title"
)
;
Trace
.
d
(
title
+
":onCreate"
)
;
}
@Override
public
void
onResume
(
)
{
super
.
onResume
(
)
;
Trace
.
d
(
title
+
":onResume"
)
;
}
@Override
public
View
onCreateView
(
LayoutInflater
inflater
,
ViewGroup
container
,
Bundle
savedInstanceState
)
{
Trace
.
d
(
title
+
":onCreateView"
)
;
tv
=
new
TextView
(
getActivity
(
)
)
;
return
tv
;
}
@Override
public
void
fetchData
(
)
{
tv
.
setText
(
title
)
;
/** * 在这里请求网络。 */
}
}
|