几个概念
- Subject 抽象主题角色(你自己):也就是抽象的被观察者对象,里面保存了所有的观察者对象引用列表,提供了注册和反注册的功能。
- ConcreteSubject具体的主题角色(你的举动):将有关状态存入各ConcreteObserver对象 当它的状态发送改变时,向它的各个观察者发出通知 。
- Observer 抽象观察者(女朋友基类) :为所有的具体观察者定义一个接口,在得到通知时更新自己。
- ConcreteObserver 具体观察者(具体女朋友):维护一个指向ConcreteObserver对象的引用 ,存储有关状态,这些状态应与目标的状态保持一致,实现Observer的更新接口是自身状态与目标的状态保持一致
具体方案实现:
(1)EventSubjectInterface:抽象的主题角色实现
/**
* 抽象的主题角色
* @author zhiwu_yan
* @since 2015年04月06日
* @version 1.0
*/
public interface EventSubjectInterface {
/**
* 注册观察者
* @param observer
*/
public void registerObserver(EventObserver observer);
/**
* 反注册观察者
* @param observer
*/
public void removeObserver(EventObserver observer);
/**
* 通知注册的观察者进行数据或者UI的更新
*/
public void notifyObserver(String eventType);
}
(2)EventSubject:具体的主题角色的实现
/**
* 具体的主题角色的实现,这里用来监听事件的发生,采用单例模式来实现
* @author zhiwu_yan
* @since 2015年04月06日
* @version 1.0
*/
public class EventSubject implements EventSubjectInterface{
private List<EventObserver> mEventObservers=new ArrayList<EventObserver>();
private static volatile EventSubject mEventSubject;
private EventSubject(){
}
public synchronized static EventSubject getInstance(){
if(mEventSubject ==null){
mEventSubject =new EventSubject();
}
return mEventSubject;
}
@Override
public void registerObserver(EventObserver observer) {
synchronized (mEventObservers){
if(observer!=null){
if(mEventObservers.contains(observer)){
return;
}
mEventObservers.add(observer);
}
}
}
@Override
public void removeObserver(EventObserver observer) {
synchronized (mEventObservers){
int index = mEventObservers.indexOf(observer);
if (index >= 0) {
mEventObservers.remove(observer);
}
}
}
@Override
public void notifyObserver(String eventType) {
if(mEventObservers!=null && mEventObservers.size()>0 && eventType!=null){
for(EventObserver observer:mEventObservers){
observer.dispatchChange(eventType);
}
}
}
}
(3)EventObserverInterface:抽象观察者对象
/**
* 观察者接口
* @author zhiwu_yan
* @since 2015年04月06日
* @version 1.0
*/
public interface EventObserverInterface {
/**
* 根据事件进行数据或者UI的更新
* @param eventType
*/
public void dispatchChange(String eventType);
}
(4)EventObserver:具体的抽线观察者
/**
* 用于更新UI,这里执行更新UI的onChange方法
* @author zhiwu_yan
* @since 2015年04月06
* @version 1.0
*/
public abstract class EventObserver implements EventObserverInterface {
private Handler mHandler;
public EventObserver(){
mHandler=new Handler(Looper.getMainLooper());
}
public abstract void onChange(String eventType);
@Override
public void dispatchChange(String eventType){
mHandler.post(new NotificationRunnable(eventType));
}
private final class NotificationRunnable implements Runnable{
private String mEventType;
public NotificationRunnable(String eventType){
this.mEventType=eventType;
}
@Override
public void run() {
EventObserver.this.onChange(mEventType);
}
}
}
(5)前面已经说过了,Android里面我们需要定义一个带观察者模式的BaseActivity用来给某些需要监听的业务的Activity使用,这样只要继承了该Activity的都是一个具体的观察者对象。
/**
* 带有观察者模式的Activity,本质上就是观察者
* @author zhiwu_yan
* @since 2015年04月6日 20:41
* @version 1.0
*/
public abstract class BaseObserverActivity extends ActionBarActivity {
private ActivityEventObserver mActivityEventObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivityEventObserver=new ActivityEventObserver(this);
registerObserver(mActivityEventObserver);
}
@Override
protected void onDestroy() {
super.onDestroy();
removeObserver(mActivityEventObserver);
}
public void registerObserver(EventObserver observer) {
final String[] observerEventTypes=getObserverEventType();//获取所有需要监听的业务类型
if(observerEventTypes!=null && observerEventTypes.length>0){
final EventSubject eventSubject=EventSubject.getInstance();
eventSubject.registerObserver(observer);
}
}
public void removeObserver(EventObserver observer) {
final String[] observerEventTypes=getObserverEventType();//获取所有需要监听的业务类型
if(observerEventTypes!=null && observerEventTypes.length>0){
final EventSubject eventSubject=EventSubject.getInstance();
eventSubject.removeObserver(observer);
}
}
/**
* 该方法会在具体的观察者对象中调用,可以根据事件的类型来更新对应的UI,这个方法在UI线程中被调用,
* 所以在该方法中不能进行耗时操作,可以另外开线程
* @param eventType 事件类型
*/
protected abstract void onChange(String eventType);
/**
* 通过这个方法来告诉具体的观察者需要监听的业务类型
* @return
*/
protected abstract String[] getObserverEventType();
private static class ActivityEventObserver extends EventObserver {
//添加弱引用,防止对象不能被回收
private final WeakReference<BaseObserverActivity> mActivity;
public ActivityEventObserver(BaseObserverActivity activity){
super();
mActivity=new WeakReference<BaseObserverActivity>(activity);
}
@Override
public void onChange(String eventType) {
BaseObserverActivity activity=mActivity.get();
if(activity!=null){
activity.onChange(eventType);
}
}
}
}
另外我们需要定义一个可以动态扩展的事件类型:EventType
/**
* 所有的业务类型,在这里写,方便管理
* @author zhiwu_yan
* @since 2015年04月06日
* @version 1.0
*/
public class EventType {
private static volatile EventType mEventType;
private final static Set<String> eventsTypes = new HashSet<String>();
public final static String UPDATE_MAIN="com.updateMain";
public final static String UPDATE_Text="com.updateText";
private EventType(){
eventsTypes.add(UPDATE_MAIN);
eventsTypes.add(UPDATE_Text);
}
public static EventType getInstance(){
if(mEventType==null){
mEventType=new EventType();
}
return mEventType;
}
public boolean contains(String eventType){
return eventsTypes.contains(eventType);
}
}
我这里主要定义个2个事件类型,如果需要你可以定义N个事件类型,只要把你需要定义的事件添加到事件类表里面去就可以了。
我们在通知某个页面需要更新的时候只需呀调用如下方法:
EventSubject eventSubject=EventSubject.getInstance();
EventType eventTypes=EventType.getInstance();
if(eventTypes.contains(eventType)){
eventSubject.notifyObserver(eventType);
}
为了便于管理我们也新建一个工具类:
/**
* 通知中心,用来通知更新数据或者UI,采用单例模式
* @author zhiwu_yan
* @since 2015年04月6日
* @version 1.0
*/
public class Notify {
private static volatile Notify mNotify;
private Notify(){
}
public static Notify getInstance(){
if(mNotify==null){
mNotify=new Notify();
}
return mNotify;
}
public void NotifyActivity(String eventType){
EventSubject eventSubject=EventSubject.getInstance();
EventType eventTypes=EventType.getInstance();
if(eventTypes.contains(eventType)){
eventSubject.notifyObserver(eventType);
}
}
}
到这里基本的框架就完成,我们看看怎么使用。
使用方法
定义一个A页面:MainActivity。这个页面是一个观察者,需要监听来自其他页面的一些通知,一旦有修改就根据对应的的事件来做出不同的处理:
public class MainActivity extends BaseObserverActivity {
private TextView mLableTv;
private ImageView mPicIv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLableTv=(TextView) findViewById(R.id.label_tv);
mPicIv=(ImageView) findViewById(R.id.pic_iv);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.go_other_activity:
goActivity(OtherActivity.class);
return true;
}
return super.onOptionsItemSelected(item);
}
private void goActivity(Class<?> activity){
Intent intent=new Intent(this,activity);
startActivity(intent);
}
@Override
protected void onChange(String eventType) {
if(EventType.UPDATE_MAIN==eventType){
mPicIv.setImageResource(R.mipmap.pic_two);
}else if(EventType.UPDATE_Text==eventType){
mLableTv.setText("图片被更新");
}
}
@Override
protected String[] getObserverEventType() {
return new String[]{
EventType.UPDATE_MAIN,
EventType.UPDATE_Text
};
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
startActivityForResult();
}
}
主要看一下:onChange 方法:根据事件类型来更新不同的图片,而在getObserverEventType()中我们定义了该观察者需要观察的业务类型,其它业务类型则会被忽略。
我们的B页面:也就是发出通知的页面,APP上面的设置页面,唯一的作用就是通知观察者:
public class OtherActivity extends ActionBarActivity {
private Button mUpdateBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity);
mUpdateBtn=(Button) findViewById(R.id.update_edit_btn);
mUpdateBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Notify.getInstance().NotifyActivity(EventType.UPDATE_Text);
Notify.getInstance().NotifyActivity(EventType.UPDATE_MAIN);
}
});
}
}