Android观察者模式

定义

定义对象间一对多的关系,当一个对象改变时,所有和它关联的其他对象都得到该对象更新的消息,从而作出对应的处理。

简单的例子

Android内置了Observer和Observable,来看看观察者和被观察者的定义:

观察者

 public interface Observer {
	 void update(Observable var1, Object var2);
 }

被观察者

public class Observable {
  //注册观察者
    public synchronized void addObserver(Observer o) {}

    public synchronized void deleteObserver(Observer o) {}
    
   protected synchronized void setChanged() { }

  //通知观察者去更新
    public void notifyObservers() {}
   ...
		
}

来看看具体的例子:

//定义观察者
public class MyObserver implements Observer{
   	 
    @Override
public void update(Observable o,Object b){
   	 //接受到通知做相应的处理
    }	 	 
}
 //定义被观察者
public class MyObservable extends Observable{
		 
	 public void postNews(String s){
			 //标志内容发生改变
			 setChanged();
			 //通知所有观察者
			 notifyObservers(s);
			 
		 }
	 }
	  
	 main(){
		  MObserver observer = new MObserver();
		  MObservable  observable = new MObservable();
		  observable.addObserver(observer);
		  observable.postNews("发布消息了");  //此时所有的观察者都能收到这个信息
	  }

就是这么简单的一个例子,就实现了观察者模式,被观察者通知观察者的方式就是遍历内部的观察者列表,然后一个个的去调用其update()方法。

Android源码中的观察者模式

Android 源码中的ListView就用到了观察者模式,看一下具体的实现:

1.首先看自定义Adapter的实现:

private  class  MyAdapter extends  BaseAdapter{   
	     //实现四个方法
		     @Override
        public int getCount() {
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return null;
        }
     }
     

2.再看BaseAdapter的关键代码:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
	
    //数据被观察者:这个类有两个方法,notifyChanged():当数据变化时,通知所有的观察者,当数据不可用时,通知观察者。
	  /**
	    * public void notifyChanged() {
            synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
	  */
   private final DataSetObservable mDataSetObservable = new DataSetObservable();

   public boolean hasStableIds() {
        return false;
    }
    //注册观察者
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
   //取消观察者
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
	
	//观察者就两个方法:
  //	onChanged(),onInvalidated()当数据源发生改变时调用。
    
   //发送数据变化的通知,实际上就是DataSetObservable发送的通知
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
	
   public void notifyDataSetInvalidated() {
        mDataSetObservable.notifyInvalidated();
    }

}

总结:BaseAdapter里面定义了一个被观察者,在里面注册和取消观察者,当数据变化时,会通知所有的Observer,【其实BaseAdapter就是一个被观察者】BaseAdapter来源于Adapter,看看Adapter的代码:

 public interface Adapter{
		 
	//注册和取消观察者	 
    void registerDataSetObserver(DataSetObserver var1);

    void unregisterDataSetObserver(DataSetObserver var1);
	
    //	自定义Adapter要实现的四个方法*/
    int getCount();

    Object getItem(int var1);

    long getItemId(int var1);

    View getView(int var1, View var2, ViewGroup var3);
}

再来看看调用流程:

      final ListView mListView = new ListView(this);
   	
   	/**实例化Adapter类,然后设置数据*/
       MyAdapter myAdapter = new MyAdapter();	
       List<String> mlist = new ArrayList<>();		
       myAdapter.setmList(mlist);
   	
   	//这步具体做了什么操作?
       mListView.setAdapter(myAdapter);
   	
   	//setAdapter()的源码:
   	  
   	public void setAdapter(ListAdapter adapter) {
   		//如果之前已经定义过了一个Adapter,那么注销所有的数据观察者
       if (mAdapter != null && mDataSetObserver != null) {
           mAdapter.unregisterDataSetObserver(mDataSetObserver);
       }


       if (mAdapter != null) {
           mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
           mOldItemCount = mItemCount;
   		
   		//从我们实现的getCount()方法中获取实际的数据数量
           mItemCount = mAdapter.getCount();
           checkFocus();
           //创建观察者:关键地方,AdapterDataSetObserver继承自DataSetObserver,实现了onChanged()方法,并在其中执行更新布局的方法。
           mDataSetObserver = new AdapterDataSetObserver();
   		//注册观察者,实际上就是调用了DataSetObservable的registerDataSetObserver(),将观察者和被观察者关联了起来
           mAdapter.registerDataSetObserver(mDataSetObserver);
   		//....
       } else {
           mAreAllItemsSelectable = true;
           checkFocus();
           // Nothing selected
           checkSelectionChanged();
       }
     //绘制UI
       requestLayout();
   }
   
   //AdapterDataSetObserver的onChanged()方法
   class AdapterDataSetObserver extends DataSetObserver {

   private Parcelable mInstanceState = null;

   @Override
   public void onChanged() {
       mDataChanged = true;
       mOldItemCount = mItemCount;
       mItemCount = getAdapter().getCount();

       // Detect the case where a cursor that was previously invalidated has
       // been repopulated with new data.
       if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
               && mOldItemCount == 0 && mItemCount > 0) {
           AdapterView.this.onRestoreInstanceState(mInstanceState);
           mInstanceState = null;
       } else {
           rememberSyncState();
       }
       checkFocus();
       requestLayout();
   }

   //...

}

这个流程如下:

1.用户创建了ListView和自定义的Adapter,通过setAdaper()将listView和Adapter关联
											
2.Adapter内部创建了观察者和被观察者,并将观察者注册给被观察者(BaseAdapter即是被观察者)
															     
3.当用户数据源发生改变时,必须调用adapter.notifyDataSetChanged方法,此时BaseAdapter内部的DataSetObservable会通知所有的观察者
                                             
4.当观察者收到了数据源发生改变时,执行OnChanged()方法,更新UI布局(requestLayout)(ListView里面封装了观察者)

综上:就是ListView所用到的完整的观察者模式的流程。

观察者模式除了ListView,还有BroadcastReceiver:

1、注册广播的方法:
registerReceiver(new BraodRE(),intentFilter);

2、实际上是执行ContextWapper的regist方法
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}

3、mBase是ContextImpl的实例
register最终到达ContextImpl.registerReceiverInternal函数中,通过mPackageInfo.getReceiverDispatcher函数获得一个IIntentReceiver接口对象rd,这是一个Binder对象,接下来会把它传给ActivityManagerService,ActivityManagerService在收到相应的广播时,就会通过这个Binder对象来通知Activity来接受。

以下几个事件订阅框架就使用了观察者模式,对比下各自的优缺点如下:

1.EventBus  :订阅函数可以异步执行,name pattern 模式,效率高。但使用不方便

2.Otto : 不能异步,使用注解,方便使用,效率比EventBus低

3.AndroidEventBus :可异步,订阅函数支持tag(类似于BroadcastReceiver的action),效率低于EventBus

还是根据实际情况来选择。

猜你喜欢

转载自blog.csdn.net/qq_26984087/article/details/86592598