概述
通常來說,解決activity和fragment通信的問題。我們都是采用如下幾種方式,
handler,廣播,EvnetBus,接口等。那么有沒有一種更好的方式來實現(xiàn)呢,最近項目一只在使用Rx,這里參照了一下Rx的設(shè)計來解決如上問題。先來說說常用的幾種方式。
handler方式
這是一種最不好的初級方式,在fragment中調(diào)用activity中的handler發(fā)送信息,activity處理信息。缺點也十分明顯,耦合性極強,并且獲取不了activity的反饋,總之體驗十分不好。
廣播
這是一種另類的玩法,個人感覺大材小用了。廣播適用于一對多且接收者不明確的情況下,
而且廣播傳播的信息需要實現(xiàn)序列化借口,總之是一種耗費性能的方式。
EvnetBus
EvnetBus作為一款事件總線存在,可以用于Action的傳遞,但是這種方式的缺點有:是用反射(對性能有影響),EvnetBus發(fā)送者和接受者分離嚴(yán)重,不好維護,且不可以獲取activity反饋,也不是十分理想。
接口
之前處理這類問題一直也是適應(yīng)這種方式,總體來講還是很不錯。但是也有缺點,當(dāng)項目大了的時候,就需要定義很多的接口,這時候就容易混淆,不好維護。
新大陸
總結(jié)一下Rx的設(shè)計思路,Rx和設(shè)計模式中的觀察者十分類似。activity和fragment通信,實質(zhì)上就是所謂事件的傳遞和響應(yīng),只是這個事件是一個特殊的事件,就是可以執(zhí)行的方法(js中function也可以是參數(shù)),那么如果activity需要監(jiān)聽fragment的事件,只需要觀察其相應(yīng)事件即可,fragment同理。
如果對觀察者不熟悉的可以看一下:這就是觀察者模式
Observable
public interface ObservableInterface<T, P, R> {
/**
* 根據(jù)名稱注冊觀察者
*/
void registerObserver(String name, T observer);
/**
* 根據(jù)名稱反注冊觀察者
*/
void removeObserver(String name);
/**
* 根據(jù)觀察者反注冊
*/
void removeObserver(T observer);
/**
* 根據(jù)名稱和觀察者反注冊
*/
void removeObserver(String name, T observer);
/**
* 根據(jù)名稱獲取觀察者
*/
Set<T> getObserver(String name);
/**
* 清除觀察者
*/
void clear();
/**
* 通知觀察者
*
* @param name 名稱
* @param p 參數(shù)
* @return 返回值
*/
R notify(String name, P... p);
}
Observer
public interface Function<Result, Param> {
Result function(Param... data);
}
這里的Observer就是一個方法的抽象,包含 參數(shù) 和 返回值。在Activity和Fragment中傳遞的就是Fuction,在需要監(jiān)聽的地方注冊事件,在適當(dāng)?shù)牡胤接|發(fā)事件。下面看一下Observable的具體實現(xiàn)
ObservableManager
public class ObservableManager<Param, Result>
implements ObservableInterface<Function, Param, Result> {
private static final String TAG = "ObservableManager";
private HashMap<String, Set<Function>> _mapping;
private final Object _lockObj = new Object();
private static ObservableManager _instance;
public ObservableManager() {
this._mapping = new HashMap<>();
}
public static ObservableManager newInstance() {
if (_instance == null) _instance = new ObservableManager();
return _instance;
}
@Override public void registerObserver(String name, Function observer) {
synchronized (_lockObj) {
Set<Function> observers;
if (!_mapping.containsKey(name)) {
observers = new HashSet<>();
_mapping.put(name, observers);
} else {
observers = _mapping.get(name);
}
observers.add(observer);
}
}
@Override public void removeObserver(String name) {
synchronized (_lockObj) {
_mapping.remove(name);
}
}
@Override public void removeObserver(Function observer) {
synchronized (_lockObj) {
for (String key : _mapping.keySet()) {
Set<Function> observers = _mapping.get(key);
observers.remove(observer);
}
}
}
@Override public void removeObserver(String name, Function observer) {
synchronized (_lockObj) {
if (_mapping.containsKey(name)) {
Set<Function> observers = _mapping.get(name);
observers.remove(observer);
}
}
}
@Override public Set<Function> getObserver(String name) {
Set<Function> observers = null;
synchronized (_lockObj) {
if (_mapping.containsKey(name)) {
observers = _mapping.get(name);
}
}
return observers;
}
@Override public void clear() {
synchronized (_lockObj) {
_mapping.clear();
}
}
public Result notify(String name, Param... param) {
synchronized (_lockObj) {
if (_mapping.containsKey(name)) {
Set<Function> observers = _mapping.get(name);
for (Function o : observers) {
return (Result) o.function(param);
}
}
return null;
}
}
}
這里才用了一個HashMap來存儲所有Observer集合,觸發(fā)事件后就輪詢集合循序之行,這就是觀察者其中之一的缺點,一個Observer可能阻塞,影響其他執(zhí)行。
使用
Activity中注冊Function事件,F(xiàn)ragment中出發(fā)Function事件,執(zhí)行的到結(jié)果,反之亦然。
// 注冊事件,Activity實現(xiàn)Function接口
ObservableManager.newInstance().registerObserver(FUNCTION_WITH_PARAM_AND_RESULT, this);
//觸發(fā)事件,并獲得返回值
Object notify = ObservableManager.newInstance()
.notify(MainActivity.FUNCTION_WITH_PARAM_AND_RESULT, "我是fragment傳到activity的參數(shù)1", fragmentActivity,
fragmentResult);
//事件執(zhí)行,實現(xiàn)于Function接口
@Override public Object function(Object[] data) {
String text = activityResult.getText().toString() + "\n\n\n";
activityResult.setText(text + "fragment調(diào)用我成功,獲取到參數(shù) :" + Arrays.asList(data));
return "我是activity的返回結(jié)果";
}
最終效果: