欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android學(xué)習(xí)之Flux架構(gòu)入門

 更新時間:2016年08月14日 11:24:53   投稿:daisy  
Flux是Facebook在14年提出的一種Web前端架構(gòu),主要用來處理復(fù)雜的UI邏輯的一致性問題(當(dāng)時是為了解決Web頁面的消息通知問題)。接下來從其特點和使用上來介紹Flux架構(gòu)。本文主要目的是讓你對Flux的一個架構(gòu)大體面貌有個了解。

Flux 架構(gòu)介紹

Flux 架構(gòu) 被Facebook使用來構(gòu)建他們的客戶端web應(yīng)用。跟Clean Architecture一樣,它不是為移動應(yīng)用設(shè)計的,但是它的特性和簡單可以讓我們很好的在安卓項目中采用。

Flux模式最大的特點是單向的數(shù)據(jù)流,它的UI狀態(tài)更新模式繼承了MVC模式的設(shè)計思想。Flux并不是具體的框架,而是一套處理UI問題的模式,Android Flux同樣不是具體的框架,你不需要導(dǎo)入或者集成任何新的代碼就可以使用,而你需要做的事情是了解這套思想、遵循這種開發(fā)模式,查看我們提供的Android代碼示例,寫自己的代碼。

要理解Flux,有兩個關(guān)鍵的特點

1、數(shù)據(jù)流總是單向的

      一個單向的數(shù)據(jù)流 是 Flux 架構(gòu)的核心,也是它簡單易學(xué)的原因。就如下面討論的,在進(jìn)行應(yīng)用測試的時候,它提供了非常大的幫助。

2、應(yīng)用被分成三個主要部分:

     . View: 應(yīng)用的界面。這里創(chuàng)建響應(yīng)用戶操作的action。

     . Dispatcher: 中心樞紐,傳遞所有的action,負(fù)責(zé)把它們運達(dá)每個Store。

     . Store: 維護(hù)一個特定application domain的狀態(tài)。它們根據(jù)當(dāng)前狀態(tài)響應(yīng)action,執(zhí)行業(yè)務(wù)邏輯,同時在完成的時候發(fā)出一個change事件。這個事件用于view更新其界面。

     這三個部分都是通過Action來通信的:一個簡單的基本對象,以類型來區(qū)分,包含了和操作相關(guān)的數(shù)據(jù)。

Flux Android 架構(gòu)

在安卓開發(fā)中使用Flux設(shè)計規(guī)范的目的是建立一個在簡單性與易擴展易測試之間都比較平衡的架構(gòu)。

第一步是找到Flux元素和安卓app組件之間的映射。

其中兩個元素非常容易找到與實現(xiàn)。

View: Activity o或者Fragment

Dispatcher: 一個事件總線( event bus),在我的例子中將使用Otto,但是其它任何實現(xiàn)都應(yīng)該是ok的。

Actions

Actions也不復(fù)雜。它們的實現(xiàn)和POJO一樣簡單,有兩個主要屬性:

     1、Type: 一個String,定義了事件的類型。

     2、Data: 一個map,裝載了本次操作。

Store是Flux理論中最難的部分。

Stores響應(yīng)Dispatcher發(fā)出的Action,執(zhí)行業(yè)務(wù)邏輯并發(fā)送change事件。Stores的唯一輸出是這單一的事件:change。其它對Store內(nèi)部狀態(tài)感興趣的組件必須監(jiān)聽這個事件,同時使用它獲取需要的數(shù)據(jù)。最后,stores必須對外公開一個獲取application狀態(tài)的接口。這樣,view元素可以查詢Stores然后相應(yīng)的更新UI。

這里通過一個簡單的小demo來講述整個流程。我們的界面上有一個Button和一個TextView,點擊Button后讓TextView顯示出文字。常規(guī)的實現(xiàn),直接在Activity中完成邏輯,MVP模式,在Presenter層來進(jìn)行,對于Flux架構(gòu),我們要怎么實現(xiàn)呢。通過上圖我們可以看到,View會產(chǎn)生Action,然后被Dispatcher進(jìn)行調(diào)度,經(jīng)過Store相應(yīng)處理,將數(shù)據(jù)顯示出來。

如何產(chǎn)生Action

首先要知道Action是什么樣

public class Action {

  private final String type;
  private final HashMap<String, Object> data;

  public Action(String type, HashMap<String, Object> data) {
    this.type = type;
    this.data = data;
  }

  public static Builder type(String type) {
    return new Builder().with(type);
  }

  public String getType() {
    return type;
  }

  public HashMap getData() {
    return data;
  }

  public static class Builder {
    private String type;
    private HashMap<String, Object> data;

    Builder with(String type) {
      if(type == null) {
        throw new IllegalArgumentException("Type may not be null.");
      }
      this.type = type;
      this.data = new HashMap<>();
      return this;
    }

    public Builder bundle(String key, Object value) {
      if (key == null) {
        throw new IllegalArgumentException("Key may not be null.");
      }
      if(value == null) {
        throw new IllegalArgumentException("Value may not be null.");
      }
      data.put(key, value);
      return this;
    }

    public Action build() {
      if (TextUtils.isEmpty(type)) {
        throw new IllegalArgumentException("At least one key is required.");
      }
      return new Action(type, data);
    }
  }
}

每一個Action有兩個屬性,一個來標(biāo)記Type,另一個字段來存儲傳送的數(shù)據(jù),通過Map來存放。

對于Action Type,我們可以通過一個接口或者類來進(jìn)行記錄,將所有的類型保存在其中。方便我們的調(diào)用。

public interface ShowActions {
  String TODO_SHOW = "todo-show";
  String GET_TEXT = "get-text";
}

如何創(chuàng)建Action,定義一個類,專門用來根據(jù)我們可能會出現(xiàn)的各種View的事件,定義出來各種Action。

public class ActionsCreator {

  private static ActionsCreator instance;

  final Dispatcher mDispatcher;

  ActionsCreator(Dispatcher dispatcher){
    mDispatcher = dispatcher;
  }

  public static ActionsCreator get(Dispatcher dispatcher) {
    if (instance == null) {
      instance = new ActionsCreator(dispatcher);
    }
    return instance;
  }

  public void create(String text) {
    mDispatcher.dispatch(ShowActions.TODO_SHOW, ShowActions.GET_TEXT, text);
  }

在我們準(zhǔn)備用ActionsCreator來創(chuàng)建Action的時候,我們并沒有直接new Action這種方式來做,而是將其通過調(diào)度器,對其進(jìn)行了分發(fā)。這里的事件分發(fā),我們使用的是OttoBus來進(jìn)行事件的分發(fā)。

public class Dispatcher {

  private final Bus bus;
  private static Dispatcher instance;

  Dispatcher(Bus bus){
    this.bus = bus;
  }

  public static Dispatcher get(Bus bus) {
    if (instance == null) {
      instance = new Dispatcher(bus);
    }
    return instance;
  }

  public void register(final Object cls) {
    bus.register(cls);
  }

  public void unRegister(final Object cls) {
    bus.unregister(cls);
  }

  public void emitChange(Store.StoreChangeEvent o) {post(o);}

  public void dispatch(String type, Object... data) {
    if(TextUtils.isEmpty(type)) {
      throw new IllegalArgumentException("Type must not be empty");
    }

    if (data.length % 2 != 0) {
      throw new IllegalArgumentException("Data must be a valid list of key");
    }

    Action.Builder actionBuilder = Action.type(type);
    for (int i = 0; i < data.length; i++) {
      String key = (String) data[i++];
      Object value = data[i++];
      actionBuilder.bundle(key, value);
    }
    post(actionBuilder.build());
  }

  private boolean isEmpty(String type) {
    return TextUtils.isEmpty(type);
  }

  private void post(final Object event) {
    bus.post(event);
  }
}

在調(diào)度的過程中,我們將傳遞進(jìn)來的數(shù)據(jù)進(jìn)行一個解析,然后根據(jù)數(shù)據(jù)創(chuàng)建出相應(yīng)的Action,然后對Action進(jìn)行分發(fā),這個時候關(guān)注了相應(yīng)的ActionStore就會開始根據(jù)相應(yīng)的Action開始執(zhí)行相應(yīng)的操作。在Store中,聲明了一個抽象方法onAction來負(fù)責(zé)進(jìn)行對于Action的判斷和分發(fā),然后定義了StoreChangeEvent接口作為事件變化,當(dāng)有變化的時候,通過這個進(jìn)行傳遞,我們可以自己實現(xiàn)這個接口,然后在里面添加一些方法和字段用來攜帶數(shù)據(jù)。

public abstract class Store {
  final Dispatcher mDispatcher;

  protected Store(Dispatcher dispatcher) {
    this.mDispatcher = dispatcher;
  }

  void emitStoreChange() {
    mDispatcher.emitChange(changeEvent());
  }

  abstract StoreChangeEvent changeEvent();

  public abstract void onAction(Action action);

  public interface StoreChangeEvent {}

}

我們自定義的Store類

public class ShowStore extends Store {

  private static ShowStore instance;
  private String showText;

  public ShowStore(Dispatcher dispatcher){
    super(dispatcher);
  }

  public static ShowStore get(Dispatcher dispatcher) {
    if (instance == null) {
      instance = new ShowStore(dispatcher);
    }
    return instance;
  }

  @Subscribe
  public void onAction(Action action) {
    switch (action.getType()) {
      case ShowActions.TODO_SHOW :
        showText = ((String)action.getData().get(ShowActions.GET_TEXT));
        Log.i("showText", showText);
        emitStoreChange();
        break;
      default:
        break;
    }
  }

  public String getShowText(){
    return showText;
  }

  @Override
  StoreChangeEvent changeEvent() {
    return new ShowChangeEvent();
  }

  public class ShowChangeEvent implements StoreChangeEvent {

  }
}

然后我們在View也就是Activity中訂閱了變化時間的方法,這個時候就可以實現(xiàn)對于View中的數(shù)據(jù)的一個動態(tài)更新。

 @Subscribe
  public void showText (ShowStore.ShowChangeEvent event){
    mTextView.setText(mShowStore.getShowText());
   }

總結(jié)

通過Flux架構(gòu),使用的流程是,我們的View的事件會攜帶數(shù)據(jù),通過一個ActionsCreate創(chuàng)建一個Type的Action,實際完成過程是在Dispatcher的dispatch中,然后再將這個Action丟給訂閱了該Action的Store方法中,在這里完成各種邏輯,處理,甚至是可以發(fā)起網(wǎng)絡(luò)請求獲取數(shù)據(jù),處理完成,可以將結(jié)果封裝成一個事件,然后這個事件會再次通過調(diào)度器中的emitChangeEvent將事件傳遞給訂閱了該事件的函數(shù),而這個接收響應(yīng)事件的函數(shù)被我們定義在我們View中,從而實現(xiàn)對于我們View的更新。以上就是本文的全部內(nèi)容了,希望本文的內(nèi)容對大家學(xué)習(xí)Flux架構(gòu)有所幫助。

相關(guān)文章

最新評論