亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Android Flux架構(gòu)初探

blankyao / 2677人閱讀

摘要:跟一樣,它不是為移動(dòng)應(yīng)用設(shè)計(jì)的,但是它的特性和簡單可以讓我們很好的在安卓項(xiàng)目中采用。架構(gòu)在安卓開發(fā)中使用設(shè)計(jì)規(guī)范的目的是建立一個(gè)在簡單性與易擴(kuò)展易測試之間都比較平衡的架構(gòu)。第一步是找到元素和安卓組件之間的映射。一個(gè),裝載了本次操作。

序言

之前寫過一篇關(guān)于Android項(xiàng)目如何架構(gòu)的,有MVC和MCVP,前幾天又看到了新的一種架構(gòu),當(dāng)然并不是新出的,出了有一段時(shí)間,當(dāng)前被應(yīng)用的并不是很普遍,接下來從其特點(diǎn)和使用上來介紹Flux架構(gòu)。本文主要目的是讓你對Flux的一個(gè)架構(gòu)大體面貌有個(gè)了解。

Flux 架構(gòu)介紹

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

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

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

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

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

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

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

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

Flux Android 架構(gòu)

在安卓開發(fā)中使用Flux設(shè)計(jì)規(guī)范的目的是建立一個(gè)在簡單性與易擴(kuò)展易測試之間都比較平衡的架構(gòu)。
第一步是找到Flux元素和安卓app組件之間的映射。
其中兩個(gè)元素非常容易找到與實(shí)現(xiàn)。
View: Activity o或者Fragment
Dispatcher: 一個(gè)事件總線( event bus),在我的例子中將使用Otto,但是其它任何實(shí)現(xiàn)都應(yīng)該是ok的。
Actions
Actions也不復(fù)雜。它們的實(shí)現(xiàn)和POJO一樣簡單,有兩個(gè)主要屬性:
Type: 一個(gè)String,定義了事件的類型。
Data: 一個(gè)map,裝載了本次操作。
Store是Flux理論中最難的部分。
Stores響應(yīng)Dispatcher發(fā)出的Action,執(zhí)行業(yè)務(wù)邏輯并發(fā)送change事件。Stores的唯一輸出是這單一的事件:change。其它對Store內(nèi)部狀態(tài)感興趣的組件必須監(jiān)聽這個(gè)事件,同時(shí)使用它獲取需要的數(shù)據(jù)。最后,stores必須對外公開一個(gè)獲取application狀態(tài)的接口。這樣,view元素可以查詢Stores然后相應(yīng)的更新UI。

這里通過一個(gè)簡單的小demo來講述整個(gè)流程。我們的界面上有一個(gè)Button和一個(gè)TextView,點(diǎn)擊Button后讓TextView顯示出文字。常規(guī)的實(shí)現(xiàn),直接在Activity中完成邏輯,MVP模式,在Presenter層來進(jìn)行,對于Flux架構(gòu),我們要怎么實(shí)現(xiàn)呢。通過上圖我們可以看到,View會(huì)產(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 data;

    public Action(String type, HashMap 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 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);
        }
    }
}

每一個(gè)Action有兩個(gè)屬性,一個(gè)來標(biāo)記Type,另一個(gè)字段來存儲(chǔ)傳送的數(shù)據(jù),通過Map來存放。
對于Action Type,我們可以通過一個(gè)接口或者類來進(jìn)行記錄,將所有的類型保存在其中。方便我們的調(diào)用。

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

如何創(chuàng)建Action,定義一個(gè)類,專門用來根據(jù)我們可能會(huì)出現(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的時(shí)候,我們并沒有直接new Action這種方式來做,而是將其通過調(diào)度器,對其進(jìn)行了分發(fā)。這里的事件分發(fā),我們使用的是Otto的Bus來進(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)行一個(gè)解析,然后根據(jù)數(shù)據(jù)創(chuàng)建出相應(yīng)的Action,然后對Action進(jìn)行分發(fā),這個(gè)時(shí)候關(guān)注了相應(yīng)的Action的Store就會(huì)開始根據(jù)相應(yīng)的Action開始執(zhí)行相應(yīng)的操作。在Store中,聲明了一個(gè)抽象方法onAction來負(fù)責(zé)進(jìn)行對于Action的判斷和分發(fā),然后定義了StoreChangeEvent接口作為事件變化,當(dāng)有變化的時(shí)候,通過這個(gè)進(jìn)行傳遞,我們可以自己實(shí)現(xiàn)這個(gè)接口,然后在里面添加一些方法和字段用來攜帶數(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中訂閱了變化時(shí)間的方法,這個(gè)時(shí)候就可以實(shí)現(xiàn)對于View中的數(shù)據(jù)的一個(gè)動(dòng)態(tài)更新。

  @Subscribe
    public void showText (ShowStore.ShowChangeEvent event){
        mTextView.setText(mShowStore.getShowText());
    }
從架構(gòu)的角度看Flux

站在整體架構(gòu)的角度來看,對于我們Activity,F(xiàn)ragment中,當(dāng)我們的View非常的豐富,涉及到的邏輯非常多的時(shí)候,這個(gè)時(shí)候,在MVP的架構(gòu)下,P層將會(huì)變的非常臃腫,后期的維護(hù)將會(huì)很難了,我們可以采用的方式是將其拆分為多個(gè)p層,分別用來處理整個(gè)屏幕下的不同的View,負(fù)責(zé)響應(yīng)View的事件,處理相應(yīng)的邏輯,還一個(gè)問題是在我們的不同的model中,可能會(huì)有些一些相同的操作,而我們卻需要將其放在不同的module下的P層中,而通過Flux方式,我們可以將這些共有的邏輯完全的解耦出來,放到Store中,然后通過單向數(shù)據(jù)流傳遞的方式,將要處理的數(shù)據(jù)傳遞給Store,然后返回處理后的結(jié)果。

總結(jié)

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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/64998.html

相關(guān)文章

  • Web和Android中的Reactive

    摘要:中的常見寫法先看下這段代碼。聲明式編程,就是告訴機(jī)器你想要的是什么,讓機(jī)器想出如何去做。最獨(dú)特的特性之一,是其非侵入性的響應(yīng)式系統(tǒng)。的縮寫將遍歷此對象所有的屬性。這一過程被稱為依賴收集。組件的顯示,數(shù)據(jù)的體現(xiàn)大部分都是由承載,傳遞。 目錄 緣起 Android開發(fā)中的常見寫法 JQuery中的常見寫法 命令式編程 聲明式編程 React中的常見寫法 Vue的常見寫法 你肯定熟悉響應(yīng)...

    liangzai_cool 評論0 收藏0
  • 我的Android重構(gòu)之旅:架構(gòu)

    摘要:是的架構(gòu)的實(shí)現(xiàn)。是在年提出的一種前端架構(gòu),主要用來處理復(fù)雜的邏輯的一致性問題當(dāng)時(shí)是為了解決頁面的消息通知問題。 去年10月底來到了新公司,剛開始接手 Android 項(xiàng)目時(shí),發(fā)現(xiàn)該項(xiàng)目真的是一團(tuán)遭,項(xiàng)目開發(fā)上沒有任何架構(gòu)可言,開發(fā)人員連簡單的 MVC、MVP 都不了解,Activity 及其臃腫,業(yè)務(wù)邊界也不明確,因此我決定重新分析一下當(dāng)前主流的幾種開發(fā)架構(gòu),選出適合當(dāng)前項(xiàng)目的架構(gòu)形式...

    mylxsw 評論0 收藏0
  • Google新技術(shù):Instant App全拆解(3)——著手

    摘要:系統(tǒng)環(huán)境要求開發(fā)不是在所有的集成開發(fā)環(huán)境都可以進(jìn)行的。這里注意,的架構(gòu)方式不能為的方式,絕對不能真機(jī)的準(zhǔn)備工作運(yùn)行于及以上的系統(tǒng)手機(jī)廠商親兒子三星服務(wù)框架已安裝在手機(jī)上。 作者:Darkbug原文標(biāo)題:Google新技術(shù):Instant App全拆解(3)——著手原文鏈接:https://segmentfault.com/a/11...首發(fā)地址:http://www.doncc.org...

    CNZPH 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<