1、前言:
前一篇文章写了一个Listener监听的Adapter,但这个Adapter只能我一个用户,假如我们在两个ListView只需要同时更新数据该怎么办呢?当然你可以另外再用一个自定义的List 来处理,那有没有更好的方法呢?当然有,下面就看看怎么来实现这个功能。
2、参考:
还是参考,让我们来看看listview是怎么来观察Adapter数据变化的吧!打开BaseAdapter源码,我们会发现第一个字段就是DataSetObservable;
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
那DataSetObservable又是什么呢?看下面:
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}
它只有两个简单的方法,这两个方法也只是遍历调用了父类中的成员变量的泛型DatasetObserver的onChange()和onInvalidated()方法,再看父类Observable:
public abstract class Observable<T> {
protected final ArrayList<T> mObservers = new ArrayList<T>();
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
Observable只有一个List,并且提供了注册方法,注册方法也只是简单的把传进来的T放进List中而已;
我们知道BaseAdapter也有注册的方法,它是怎么注册的呢?让我们来看一下:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
它只是简单调用了它的成员变量的两个方法。
看到这里我们知道,BaseAdapter中通过mDatasetObserver这个成员变量拥有了一个被观察者的List,并用只要调用notifychange()或者notifyInvalidated()方法,就可以通知到每一个观察者,并调用观察者的onChange()或onInvalidated()方法;
再看看ListView吧!
ListView继承自AbsListView,AbsListView中有一个内部类:
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
@Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
}
这个内部类复写了父类的onChange()方法,父类的这个方法在AdapterView的内部类AdapterDataSetObserver中进行了实现:
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}
让我们来看看我们经常用到的更新数据用的BaseAdapter的NotifyDatasetChange()方法:
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
绕来绕去,终于明白了吧!
说白了,就是ListView是一个观察者,Adapter是一个被观察者,当你调用Adapter的NotifyDatasetChange()方法时,就是调用了DatasetObsable的notifyDatasetChange()方法,就会通知到每一个Observer,调用observer的onChange()方法,而当你调用Listview的setAdapter时:它new了一个AdapterDataSetObserver,并把它注册到了Adaper中,所以,你一调用就更新界面了!
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
int position;
if (mStackFromBottom) {
position = lookForSelectablePosition(mItemCount - 1, false);
} else {
position = lookForSelectablePosition(0, true);
}
setSelectedPositionInt(position);
setNextSelectedPositionInt(position);
if (mItemCount == 0) {
// Nothing selected
checkSelectionChanged();
}
} else {
mAreAllItemsSelectable = true;
checkFocus();
// Nothing selected
checkSelectionChanged();
}
requestLayout();
}
写了这么多,其实仔细想想,再仔细想想,只要把我们前面的Lister换成多个,当数据变化时每一个都通知到不就行了?
所以说,编程就是个思想,只要你想的到,思维方式稍加变化就有新的概念,最看不惯很多人满口的概念,还有满口的英文,好像有多神秘一样,其实,这是西方人的思维方式,不是我们中国人的。
好了,看看我们的Observer实现的多个客户端的Adapter吧!
public class ObserableList<E> extends ArrayList<E> {
private static final long serialVersionUID = -9031831111939356165L;
private ArrayList<DatasetChangeObserver> mObservers;
public void registObserver(DatasetChangeObserver listener) {
this.mObservers.add(listener);
}
private void datasetChange(){
if(!mObservers.isEmpty()){
for (DatasetChangeObserver observer : mObservers) {
observer.onDatasetChange();
}
}
}
@Override
public boolean add(E object) {
if(super.add(object)){
datasetChange();
}
return false;
}
@Override
public void add(int index, E object) {
super.add(index, object);
datasetChange();
}
@Override
public boolean addAll(Collection<? extends E> collection) {
if(super.addAll(collection)){
datasetChange();
return true;
};
return false;
}
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
if(super.addAll(index, collection)){
datasetChange();
return true;
}
return false;
}
@Override
public E remove(int index) {
E e =super.remove(index);
datasetChange();
return e;
}
@Override
public boolean remove(Object object) {
if(super.remove(object)){
datasetChange();
}
return false;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
super.removeRange(fromIndex, toIndex);
datasetChange();
}
@Override
public void clear() {
super.clear();
datasetChange();
}
@Override
public E set(int index, E object) {
E e = super.set(index, object);
datasetChange();
return e;
}
public static interface DatasetChangeObserver {
public void onDatasetChange();
}
}
如果你想更简单一些,还可以使用前面的ListenableList,这样写:
public class ObserableList2<E> extends ListenerList<E>{
private static final long serialVersionUID = -6118271325340704497L;
private ArrayList<DatasetChangeObserver> mObservers;
public void registObserver(DatasetChangeObserver listener) {
this.mObservers.add(listener);
}
public void unregistObserver(DatasetChangeObserver listener) {
this.mObservers.remove(listener);
}
@Override
public void dataSetChange() {
if(!mObservers.isEmpty()){
for (DatasetChangeObserver observer : mObservers) {
observer.onDatasetChange();
}
}
}
}
这样写完了,测试,没有问题,但是还有一个问题需要引起 重视,我们在使用我们的AutoupdataAdapter时,传进的数据只能是我们已经定义好的类,那么通用性就会大大降低,我们是不是可以这样写呢?
首先抽取一个接口:
public interface Notifyable{
//public interface NotifyList<E> extends List<E>{
public void unregistDatasetChangeListener(DatasetChangeListener listener);
public void registDatasetChangeListener(DatasetChangeListener listener);
public void datasetChange();
public static interface DatasetChangeListener {
public void onDatasetChange();
}
}
这个接口中有一个DatasetChangeListener接口,然后让ListenableList接口实现这个接口:
另:上篇中的ObserableListener改为Listenable,特此更正,方便理解!
public class ListenableList<E> extends ArrayList<E> implements Notifyable{
private static final long serialVersionUID = -9031831111939356165L;
private DatasetChangeListener mListener;
@Override
public void unregistDatasetChangeListener(DatasetChangeListener listener) {
this.mListener = listener;
}
@Override
public void registDatasetChangeListener(DatasetChangeListener listener) {
this.mListener = null;
}
@Override
public void datasetChange(){
if(mListener != null){
mListener.onDatasetChange();
}
}
@Override
public boolean add(E object) {
if(super.add(object)){
datasetChange();
return true;
}
return false;
}
@Override
public void add(int index, E object) {
super.add(index, object);
datasetChange();
}
@Override
public boolean addAll(Collection<? extends E> collection) {
if(super.addAll(collection)){
datasetChange();
return true;
};
return false;
}
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
if(super.addAll(index, collection)){
datasetChange();
return true;
}
return false;
}
@Override
public E remove(int index) {
E e =super.remove(index);
datasetChange();
return e;
}
@Override
public boolean remove(Object object) {
if(super.remove(object)){
datasetChange();
return true;
}
return false;
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
super.removeRange(fromIndex, toIndex);
datasetChange();
}
@Override
public void clear() {
super.clear();
datasetChange();
}
@Override
public E set(int index, E object) {
E e = super.set(index, object);
datasetChange();
return e;
}
}
NotifyableList继承ListenableList:
public class NotifyableList<E> extends ListenableList<E>{
private static final long serialVersionUID = -6118271325340704497L;
private ArrayList<DatasetChangeListener> mListeners = new ArrayList<DatasetChangeListener>();
@Override
public void unregistDatasetChangeListener(DatasetChangeListener listener) {
this.mListeners.remove(listener);
}
@Override
public void registDatasetChangeListener(DatasetChangeListener listener) {
this.mListeners.add(listener);
}
@Override
public void datasetChange() {
if(!mListeners.isEmpty()){
for (DatasetChangeListener observer : mListeners) {
observer.onDatasetChange();
}
}
}
}
同时,在AutoDatasetAdapter中,传的数据参数类型改为List,并改一个注册方法:
public class AutoUpdataAdapter<T> extends GeneralAdapter<T> implements DatasetChangeListener {
public AutoUpdataAdapter(int itemlayoutid, List<T> listdatas,IItemViewHolder iviewholder) {
super(itemlayoutid, listdatas,iviewholder);
}
public AutoUpdataAdapter(int itemlayoutid, List<T> listdatas,IItemViewHolder iviewholder,boolean autoupdata) {
super(itemlayoutid, listdatas,iviewholder);
setAutoupdata(autoupdata);
}
public void setAutoupdata(boolean autoupdata) {
if(mListDatas instanceof Notifyable){
if(autoupdata){
((Notifyable) mListDatas).registDatasetChangeListener(this);
}else{
((Notifyable) mListDatas).unregistDatasetChangeListener(this);
}
}else{
throw new RuntimeException("autoupdata the List must be instandeof Notifyable<T>,else do not autoupdata");
}
}
@Override
public void onDatasetChange() {
notifyDataSetChanged();
}
}
这样如果你传入的是一个普通的List,不是我们自定义的,或者不调用setAutoupdata(boolean)方法,它还是和普通的Adapter一样使用,传入的是NotifyableList类型,并调用了setAutoupdata(boolean)方法,就是我们的自动更新Adapter了!
如果你充分理解了以上思维方式 ,当然还可以根据自己的需求加一些功能。写完了,但本篇中的代码我没有测试,如果测试有问题欢迎留言!
本文源码下载: