第一部分:现象出现的原因
代码默认实现如此。
FragmentPagerAdapter调用notifyDataSetChanged后,执行mObservable.notifyChanged()。mObservable对象的初始化,是在ViewPager调用setAdapter时被赋值的,对应的类叫PagerObserver。PagerObserver的dataSetChanged方法如下:
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
|
for
(
int
i =
0
; i < mItems.size(); i++) {
final
ItemInfo ii = mItems.get(i);
final
int
newPos = mAdapter.getItemPosition(ii.object);
if
(newPos == PagerAdapter.POSITION_UNCHANGED) {
continue
;
}
if
(newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if
(!isUpdating) {
mAdapter.startUpdate(
this
);
isUpdating =
true
;
}
mAdapter.destroyItem(
this
, ii.position, ii.object);
needPopulate =
true
;
if
(mCurItem == ii.position) {
// Keep the current item in the valid range
newCurrItem = Math.max(
0
, Math.min(mCurItem, adapterCount -
1
));
needPopulate =
true
;
}
continue
;
}
if
(ii.position != newPos) {
if
(ii.position == mCurItem) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii.position = newPos;
needPopulate =
true
;
}
}
|
PagerAdapter的默认getItemPosition实现是 return POSITION_UNCHANGED。所以调用notifyDataSetChanged方法不会刷新Fragment。
第二部分:解决办法
为了让Fragment重新绘制,必须重载FragmentPagerAdapter的getItemPositon方法并修改为return POSITION_NONE。这样之前所有的Fragment都会被detach掉。
1
2
3
4
|
@Override
public
int
getItemPosition(Object object) {
return
POSITION_NONE;
}
|
如果你按上面的步骤做了,而且调用notifyDataSetChanged时候,list数据位空,那么结果是你希望看到的。但是如果list的数据在原有的基础上做了修改,但是结果你看到的Fragment上显示的信息还是之前的数据。
第三部分:Fragment不刷新的原因
如第二部分描述,旧的Fragment都会被detach掉,但是它并没有被distory掉,而是被保存下来了,保存时候存储的tag来源如下代码:
1
2
3
|
private
static
String makeFragmentName(
int
viewId,
long
id) {
return
"android:switcher:"
+ viewId +
":"
+ id;
}
|
刷新后调用FragmentPagerAdapgter的instantiateItem方法,会通过findFragmentByTag找到被detach掉的Fragment,然后再执行该Fragemnt的attach方法,最后再次执行Fragment的生命周期,所以你看到的Fragment上面的数据还是老数据。
第四部分:解决办法
如第三部分描述,如果Fragment你是通过getItem方法中去new一个Fragment出来,然后数据通过setArgument设置进去的。那么再次执行改Fragment的attach方法后,拿到的数据还是老数据。解决版本就是在instantiateItem方法中调用Fragment的自定义方法resetFragmentData(),把旧数据替换掉。注:resetFragmentData只能做数据替换,不能直接更新view,View的更新还是在调用attach方法后继续执行到onActivityCreated方法后执行刷新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
37
38
39
|
public
class
CarTypeListAdapter
extends
FragmentPagerAdapter {
private
final
ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> mRecList;
protected
ImageWorker mImageFetcher;
public
CarTypeListAdapter(FragmentManager fm, ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> recList, ImageWorker worker) {
super
(fm);
this
.mRecList = recList;
this
.mImageFetcher = worker;
}
@Override
public
Fragment getItem(
int
position) {
CarTypeInfoFragment imageFragment = CarTypeInfoFragment.newInstance(mRecList.get(position), mImageFetcher);
return
imageFragment;
}
public
Object instantiateItem(ViewGroup container,
int
position) {
CarTypeInfoFragment f = (CarTypeInfoFragment)
super
.instantiateItem(container, position);
if
(!QArrays.isEmpty(mRecList) && position >=
0
&& position < mRecList.size()){
CarTypeListMinPriceResult.CarTypeMinPrice p = mRecList.get(position);
if
(p !=
null
){
f.resetFragmentData(p);
}
}
return
f;
}
@Override
public
int
getItemPosition(Object object) {
return
POSITION_NONE;
}
@Override
public
int
getCount() {
return
mRecList ==
null
?
0
: mRecList.size();
}
}
|