Android 广播、EventBus、观察者模式

时间:2022-11-03 20:02:52
引用知乎: 最近在想安卓这边应该如何更好地分发代码,以前一直用广播,但是一般认为本地广播是三种方式中消耗时间、空间最多的一种方式,但也是同 android 相性最好的方式。因为广播属于 android 四大组件之一,在 BroadcastReceiver 中的 onReceive 方法中可以获得 Context、Intent 参数。持有这两个参数便可以调用许多 android sdk 中的方法,这一优势另外两种方式很难弥补的,无论是 EventBus 还是观察者,需要获得 Context 的话,往往都需要进行复杂的参数传递或者是依赖注入。 本地广播另外的一个优点是,许多系统级的事件都是使用广播来进行通知的,像常用的电量变化、网络状态变化、短信发送接收的状态等等。这就使得与 android 系统相关的通知,广播往往成了唯一的选择。但这并不意味着 android 系统中的通知都应该使用广播,因为相对于其它的方式而言,广播是重量级的、消耗资源较多的方式。广播的优势体现在它与 android sdk 链接的更紧密,当我们需要同 android 交互的时候,广播提供的便捷性抵消掉了它过多的资源消耗。但是对于不需要同 android 交互或是只做很少的交互的时候,使用广播往往是一种浪费 所以在不需要系统调用、进程通信的时候就可以不用广播,但是因为EventBus是基于反射的,利用方法名,来定义事件的,这会导致该类无法混淆,所以在一般情况下,使用观察者就可以达通知的目的。 根据网上的一个观察者模式: http://www.akiyamayzw.com/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F%E5%9C%A8android-%E4%B8%8A%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/ 但是把所有的观察者放在一个队列里,如果有一个事件需要通知,就需要遍历所有观察者,这感觉不太好,所以我按照EventBus的思路,改为map存储,使用事件对应订阅者列表,但是就无法通过继承父类来订阅和取消订阅,这大概就是有得有失吧。 修改的部分如下: packagecom.example.jaydon.observable;

import
android.text.TextUtils;
import
java.util.HashMap;
import
java.util.Map;
import
java.util.concurrent.CopyOnWriteArrayList;

/**
* 具体的主题角色的实现,这里用来监听事件的发生,采用单例模式来实现
* Created by Jaydon on 2015/12/20.
*/
public classEventSubjectimplementsEventSubjectInterface{
//    private List<EventObserver> mEventObservers = new ArrayList<EventObserver>();
   
private static finalMap<String,CopyOnWriteArrayList<EventObserver>>mEventObservers=newHashMap<String,CopyOnWriteArrayList<EventObserver>>();//每个事件的父类、接口
   
private static volatileEventSubjectmEventSubject;
    private
EventSubject(){
    }

   
public staticEventSubjectgetInstance(){
       
if(null==mEventSubject){
           
synchronized(EventSubject.class) {
               
if(null==mEventSubject) {
                   
mEventSubject=newEventSubject();
               
}
            }
        }
       
returnmEventSubject;
   
}

   
@Override
   
public voidregisterObserver(EventObserver observer,String eventType)throwsException {
       
if(TextUtils.isEmpty(eventType) ||null== observer) {
           
throw newException("参数不正确");
       
}
       
synchronized(mEventObservers){
            CopyOnWriteArrayList<EventObserver> observers =
mEventObservers.get(eventType);
            if
(null== observers) {
                observers =
new CopyOnWriteArrayList<>();
               
mEventObservers.put(eventType,observers);
           
}
           
if(observers.contains(observer)){
               
throw newException("已经注册过");
           
}
            observers.add(observer)
;
       
}
    }

   
@Override
   
public voidremoveObserver(EventObserver observer,String eventType)throwsException {
       
if(TextUtils.isEmpty(eventType) ||null== observer) {
           
throw newException("参数不正确");
       
}
       
synchronized(mEventObservers){
            CopyOnWriteArrayList<EventObserver> observers =
mEventObservers.get(eventType);
            if
(null== observers) {
               
throw newException("未注册过");
           
}
           
intindex = observers.indexOf(observer);
            if
(index >=0) {
               
mEventObservers.remove(observer);
           
}
        }
    }

   
@Override
   
public voidnotifyObserver(String eventType)throwsException {
       
if(TextUtils.isEmpty(eventType)) {
           
throw newException("参数不正确");
       
}
        CopyOnWriteArrayList<EventObserver> observers =
mEventObservers.get(eventType);
        if
(null== observers) {
           
throw newException("未注册过");
       
}
       
if(mEventObservers!=null&&mEventObservers.size()>0){
           
for(EventObserver observer : observers){
                observer.dispatchChange(eventType)
;
           
}
        }

    }
} 如此使用: packagecom.example.jaydon.activity;

import
android.os.Bundle;
import
android.support.design.widget.FloatingActionButton;
import
android.support.design.widget.Snackbar;
import
android.support.v7.widget.Toolbar;
import
android.view.View;
import
com.example.jaydon.R;
import
com.example.jaydon.observable.EventObserver;
import
com.example.jaydon.observable.EventSubject;
import
com.example.jaydon.observable.EventType;
import
com.example.jaydon.observable.Notify;

public class
MainActivityextendsBaseActivity {
   
privateActivityEventObservermActivityEventObserver;

   
@Override
   
protected voidonCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
mActivityEventObserver=newActivityEventObserver(this);
       
registerObserver(mActivityEventObserver);
       
initView();
   
}

   
private voidinitView() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.
toolbar);
       
setSupportActionBar(toolbar);

       
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
       
fab.setOnClickListener(newView.OnClickListener() {
           
@Override
           
public voidonClick(View view) {
                Snackbar.
make(view
,"Replace with your own action",Snackbar.LENGTH_LONG)
                        .setAction(
"Action", null).show();
               
Notify.getInstance().NotifyActivity(EventType.UPDATE_TEXT);
               
Notify.getInstance().NotifyActivity(EventType.UPDATE_MAIN);
           
}
        })
;
   
}

   
@Override
   
protected voidonDestroy() {
       
super.onDestroy();
       
removeObserver(mActivityEventObserver);
   
}


   
public voidregisterObserver(EventObserver observer) {
       
finalString[] observerEventTypes = getObserverEventType();//获取所有需要监听的业务类型
       
finalEventSubject eventSubject = EventSubject.getInstance();
        if
(null!= observerEventTypes && observerEventTypes.length>0){
           
for(String eventType : observerEventTypes) {
               
try{
                    eventSubject.registerObserver(observer
, eventType);
               
}catch(Exception e) {
                    e.printStackTrace()
;
               
}
            }
        }

    }

   
public voidremoveObserver(EventObserver observer) {
       
finalString[] observerEventTypes = getObserverEventType();//获取所有需要监听的业务类型
       
finalEventSubject eventSubject = EventSubject.getInstance();
        if
(null!= observerEventTypes && observerEventTypes.length>0){
           
for(String eventType : observerEventTypes) {
               
try{
                    eventSubject.removeObserver(observer
, eventType);
               
}catch(Exception e) {
                    e.printStackTrace()
;
               
}
            }
        }
    }


   
@Override
   
protected voidonChange(String eventType) {
       
if(EventType.UPDATE_MAIN==eventType){
            showShortToast(EventType.
UPDATE_MAIN);
       
}else if(EventType.UPDATE_TEXT==eventType){
            showShortToast(EventType.
UPDATE_TEXT)
;
       
}
    }

   
@Override
   
protectedString[]getObserverEventType() {
       
return newString[]{
                EventType.
UPDATE_MAIN,
               
EventType.UPDATE_TEXT
        }
;
   
}

}