使用觀察者模式完美解決activity與fragment通信問題

概述

通常來說,解決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é)果";
 }

最終效果:

activityfragment
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容