1. 问题
在用ViewPager加载fragment浏览图片的时候,需要删除当前浏览的照片,删除后要加载下一张或者上一张照片,并且照片的位置等信息都要更新,
但是因为ViewPager每次都是预加载前一张和后一张,在删除照片之前前一张和后一张的照片信息已经加载完成了,
那这个时候该如何更新已经加载了的照片的信息呢,并且当前又该如何显示下一张照片呢,尝试了很多方法都失败了,当然也可以禁止预加载,但是用户体验不好;
经过一天的研究,发现安卓的观察者模式能够解决这个问题,于是研究了下,完美解决了。
2. 观察者模式
观察者模式的原理网上一大堆,简单点说就是定义一个被观察者和多个观察者,被观察者改变的时候通知所有的观察者都改变;
在实际使用的时候和回调函数有点相似,但是却比回调功能更强,这里不过多的介绍观察者模式了,网上有一个朋友介绍得很详细了,可以了解下:
http://www.apkbus.com/forum.php?mod=viewthread&tid=112815&extra=page%3D1&page=1
3. 解决问题
使用观察者模式,最重要的一点就是得知道谁是观察者Observer,谁是被观察者Observable,那么在本文讨论的问题中,观察者就是ViewPager中的每一项,
被观察者需要自定义一个继承自Observable的类,在这个类中做一些接口做数据的变更,需要注意一点,就是在更新数据的时候必须加上setChanged();和notifyObservers();通知观察者更新,代码如下:
public class MyObservable extends Observable {
private List<MyFileInfor> list = null;
private int position = 0;
public void setPosition(int position)
{
this.position = position;
setChanged();
notifyObservers();
}
public int getPosition()
{
return position;
}
public List<MyFileInfor> getList() {
return list;
}
public void setList(List<MyFileInfor> list) {
this.list = list;
setChanged();
notifyObservers();
}
}
被观察者定义好了,现在就定义观察者了,很简单,只需要在ViewPager中的每一个Fragment实现Observer接口,里面有一个回调函数:
/**
*callbacks
*/
@Override
public void update(Observable observable, Object data)
{
// TODO Auto-generated method stub
MyObservable myObservable = (MyObservable)observable;
/*fileList = myObservable.getList();
curPosition = myObservable.getPosition(); */
MyLog.e("curPosition-->"+ curPosition);
MyLog.e("curPosition get-->"+ myObservable.getPosition());
PublicFun.sendMessage(handler, HANDLER_UPDATE_BY_OBSERVER);
}
在这个回调函数中做界面更新,更新就很简单了,什么都不用做,只需要在删除的时候将那一张图片从列表中移除,然后和正常浏览一样更新UI就可以了;
最后就是给被观察者添加观察者了,在ViewPager的适配器中有添加Fragment和移除Fragment ,同样在这里添加观察者和被观察者:
@Override
public Fragment getItem(int position)
{
PicFullScreenViewFragment view = PicFullScreenViewFragment.newInstance(type, fileList, position, mAdapter);
viewList.add(view);
obervable.addObserver(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
final PicFullScreenViewFragment fragment = (PicFullScreenViewFragment) object;
obervable.deleteObserver(fragment);
viewList.remove(fragment);
fragment.cancelWork();
super.destroyItem(container, position, object);
}
public void updateObserver(List<MyFileInfor> list, int position)
{
obervable.setList(list);
obervable.setPosition(position);
}
其中,updateObserver函数就在删除照片操作的时候调用的,当调用这个函数时,被观察者就会通知其他观察者更新,即调用上面说的update函数。
采用观察者模式,基本上解决了问题,但是具体细节还需要自己去调整,比如说,但删除最后一张照片的时候就会出现黑屏的问题,这个问题也很好解决,
当出现黑屏的时候用手滑动一下,就会显示当前列表的最后一张照片,在代码中处理就是,当删除的是最后一张照片的时候,将ViewPager设置为当前的位置就行了,
问题基本上解决了,由于是公司的项目,不便上传源码,有疑问可以留言。
更新:
以前是按照列表一样对ViewPager进行更新操作,但是当删除其中一个View然后再notifidatasetchanged的时候,并没有达到期望的效果,当前一页变成黑色的了,所以才用观察者模式来更新ViewPager,
但是今天却看到了ViewPager的一个方法:
public int getItemPosition(Object object) {
return POSITION_NONE;
}
当删除其中一页的时候会回调这个方法更新ViewPager,自动显示下一页或者上一页,非常方便;