1. 程式人生 > >Android工程架構設計:Base Library(基層MVP框架)基於EventBus

Android工程架構設計:Base Library(基層MVP框架)基於EventBus

Base Library部分把App中Application,UI(activity,fragment)公用方法重新封裝成模板方法,並開放對子類的擴充套件。同時融入mvp設計思想,封裝成基於mvp的基層架構體系。

目錄

1,IApplication(介面):

2,BaseApplication(抽象基類)

2.1 規定Application中行為的執行規則(模板方法模式)

2.2 實現IApplication中的部分行為(通用部分)

2.3 Application關鍵方法

2.4 定義與公共行為相關的抽象方法(具體行為),供子類擴充套件

3,mvp(基層mvp架構)

3.1. mvp策略微調

3.1.1.PV之間通訊採用EventBus訊息機制替換之前的介面回撥機制。

3.1.2.增加對P的快取管理

3.2. 契約類 Contract

3.3. V層

1. Activity

3.3.2. Fragment

3.4. P層

3.4.1. Presenter

3.4.2. Event

3.5. M層

4,GlobalField

總結


 

 

1,IApplication(介面):

1,把框架內應用(Application)的通用行為抽象定義(框架內app都會用到的初始化

或者公參配置的行為方法)。

2,繼承ActivityLifecycleCallbacks介面,整合Activity生命週期回撥方法。

之後框架內所有app的自定義Application應該都實現此介面,具體行為放在各個app的Application中實現。

public interface IApplication extends Application.ActivityLifecycleCallbacks {
    void initNetworkConfig();
    void initSharedPreference(String sharedName);
    void initOtherConfig();
}

也就是說,每個app的Application做了兩部分事情,一部分是實現了公共行為(IApplication)(共性),另外一部分實現了私有行為(異性)。

2,BaseApplication(抽象基類)

public abstract class BaseApplication extends MultiDexApplication implements IApplication

BaseApplication需要做四件事情:

2.1 規定Application中行為的執行規則(模板方法模式)

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(this);
    initNetworkConfig();
    initSharedPreference(defineSharedPreferenceName());
    initOtherConfig();
}

2.2 實現IApplication中的部分行為(通用部分)

@Override
public void initNetworkConfig() {
    // init common config
}
@Override
public void initSharedPreference(String sharedName) {
    SharedUtils.initInstance(getApplicationContext(), sharedName);
}

2.3 Application關鍵方法

@Override
public void onTerminate() {
    super.onTerminate();
    unregisterActivityLifecycleCallbacks(this);
}
@Override
public void onLowMemory() {
    super.onLowMemory();
}
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

本類庫中,利用Activity生命週期回撥方法,由BaseApplication對Activity對應P層的註冊,解注行為進行統一管理。支援Activity,AppCompatActivity,FragmentActivity。

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    if (activity instanceof BaseActivity) {
        ((BaseActivity) activity).registerPresenter();
    } else if (activity instanceof BaseAppCompatActivity) {
        ((BaseAppCompatActivity) activity).registerPresenter();
    } else if (activity instanceof BaseFragmentActivity) {
        ((BaseFragmentActivity) activity).registerPresenter();
    }
}
@Override
public void onActivityDestroyed(Activity activity) {
    if (activity instanceof BaseActivity) {
        ((BaseActivity) activity).unregisterPresenter();
    } else if (activity instanceof BaseAppCompatActivity) {
        ((BaseAppCompatActivity) activity).unregisterPresenter();
    } else if (activity instanceof BaseFragmentActivity) {
        ((BaseFragmentActivity) activity).unregisterPresenter();
    }
}

2.4 定義與公共行為相關的抽象方法(具體行為),供子類擴充套件

protected abstract String defineSharedPreferenceName();
// other methods ...

3,mvp(基層mvp架構)

mvp最近很火,也很煩,各個公司,各位大神,對mvp的理解和應用各異,論壇上各種對mvp的詳解,demo,設計分析以及基於mvp的各種開源專案 ……

作者淺見:mvp就是一種架構設計思想,目的在於把UI展現層,業務邏輯處理層,資料管理層在程式碼中解耦,達到某種程度的程式碼層次清晰明瞭(我的理解:某種程度!!!)。至於實際應用中以何種方式設計實現,達到何種程度? …… 因人因專案因公司而已吧,設計成本,團隊理解力,學習成本,程式碼可讀性等等……哪種才是最好的?達到目的,適合自己就夠了,別出嚴重bug就好。另外,作者後續會對mvp的個人理解整理成文,敬請關注!

作者在接觸並應用mvp設計思想的過程中,總結到一些問題(針對標準mvp):

1,頻繁的介面呼叫和回撥:V讓P做事情,需要呼叫P的介面,P從M請求資料需要呼叫M的介面;M把資料返回給P做業務處理要呼叫P的回撥介面,P處理完業務邏輯或者業務資料返回給V做互動反饋又要呼叫V的回撥介面。 

你會發現,一套mvp程式碼寫完,光介面就定義了一火車,煩且繁!一個簡單UI互動,動輒需要2~4個甚至更多介面定義,層級解耦的開發代價是否過大呢?

2,耦合,主要是PV的耦合,很難完全避免。V依賴P,P又要持有V的介面型別,即便網上某些設計採用了各種方式極力避免(弱引用等等) …… 

那是否mvp就一定要達到一種完全解耦的效果呢?也不一定,作者從業這幾年,也拜讀過一些元件原始碼,發現一個問題,coding在封裝程式碼的時候,往往會過度追求完美(技術流往往很執著),有時候一段很簡單的程式碼,被設計的很複雜,層層封裝,層層回撥 …… 其實有時候還是適當為好吧,也要考慮開發成本,效能,程式碼可讀性,如果是作為公共元件,還要考慮學習成本,外觀介面是否便於外部呼叫等等因素(僅個人愚見,不喜勿噴,也許是因為作者程式碼能力的確有限,達不到而下意識給自己找了個藉口吧)。

以最直接的方式,最簡單的策略,儘可能高效滴實現需求。這是我對coding的理解。

上述淺見,作者在自己的mvp框架內,做了如下調整:

3.1. mvp策略微調

3.1.1PV之間通訊採用EventBus訊息機制替換之前的介面回撥機制

V單項依賴於P,避免P層持有V物件引用,P回饋給V通過EventBus封裝訊息實現。 流程就是V向P發處理命令(V呼叫P的方法),P做業務處理後,向Module層索要資料,M層獲取資料之後介面反饋給P,P針對不同業務做資料二次加工(這個部分也可以放在M,來分擔P的壓力)。P將執行結果(資料,命令)封裝成訊息(Event),通過EventBus傳送給V進行處理。(考慮到程式碼可讀性,可追溯性,訊息機制僅限於P—>V的部分,並沒有用EventBus實現PV雙向通訊)

綜述就是,在PV之間加了EventBus訊息機制,由雙向依賴變成了單項依賴,保留了業務請求介面(V—>P)

(1)  P層(BaseEvent)

Base Library在P層定義了Event基類,通過成員變數eventTag區分訊息目的UI執行緒(訊息應該傳送給哪個View,eventTag值一般為View的包名 + 類名 字串構成),通過成員變數actionId區分同一UI執行緒不同型別的邏輯操作(登入,忘記密碼,找回密碼,重新整理列表等操作型別)。

public class BaseEvent {
    //......
    /**
     * default action id for Initialization UI thread
     */
    public static final int INIT_PROCESS_ACTION_ID = 20181001;
    /**
     * for different UI thread. default value: name of current class
     */
    public String eventTag;
    /**
     * same UI thread, different action
     */
    public int actionId = INIT_PROCESS_ACTION_ID;
    //......
}

(2)V層

Base Library在V層提供了統一的Event接收入口,統一接收Event訊息,並通過eventTag過濾,使用者可以在UI執行緒通過接收到的Event的actionId進行行為分發,區別響應。

public abstract class BaseActivity<P extends BasePresenter> extends Activity implements Contract.IView {

    // ......
    @Subscribe
    @Override
    public <E extends BaseEvent> void onEventMessageReceive(E event) {
        if (null == event || !event.eventTag.equals(getSimpleTag())) {
            return;
        }
        switch (event.actionId) {
            case BaseEvent.INIT_PROCESS_ACTION_ID:
                // do sth init view
                initDataView(event);
                break;
            default:
                onHandleMessage(event);
                break;
        }
    }
    // ......

}

其中BaseEvent.INIT_PROCESS_ACTION_ID定義為初始化重新整理UI資料行為,單獨提供訊息處理介面initDataView,其餘型別訊息由onHandleMessage接收處理。

/**
 * Init data and refresh view
 * @param event BaseEvent
 * @param <E>   BaseEvent
 */
protected abstract <E extends BaseEvent> void initDataView(E event);
/**
 * receive and handle EventBus message
 * @param event BaseEvent
 * @param <E>   BaseEvent
 */
protected abstract <E extends BaseEvent> void onHandleMessage(E event);

優勢:

系統內建這套BaseEvent以及接收入口,通過eventTag區分UI執行緒(view),eventId區分執行緒內實際操作。可大大減少EventMessage(訊息類)的定義數量,改善原來EventBus對每一種訊息,都需要定義一種訊息類的情況。結合對eventId的統一定義和管理,簡化程式碼的同時,也可提高程式碼可讀性。

爭議:

如果使用系統內建這套BaseEvent以及接收入口,會導致每個註冊的觀察者類都會收到傳送的訊息:

public <E extends BaseEvent> void onEventMessageReceive(E event)

是否會影響效能呢?

作者認為微乎其微,可以忽略。策略本身實際是把原來EventBus對註冊特定Message型別的觀察者傳送訊息的點對點機制,變成了廣播。但考慮本身app實際同時有效註冊EventBus的類和方法數量有限,量級可控,效能影響可忽略。

使用者也可以拋棄Base Library內建的BaseEvent,在App層自定義一套EventMessage,並按照常規寫法,在每個註冊EventBus的類中,實現訊息接收程式碼。同時在每個App中對Base Library的BaseActivity定義中間父類,隱藏相關方法,實現對子類的無感知。

public abstract class BaseActivity<P extends BasePresenter> extends library.base.mvp.v.activity.BaseActivity<P> {

    // ......
    @Override
    protected <E extends BaseEvent> void initDataView(E event) {

    }

    @Override
    protected <E extends BaseEvent> void onHandleMessage(E event) {

    }
    // ......
}

3.1.2.增加對P的快取管理

增加對P的快取管理,制定快取策略(失效策略),有效解決由於手機橫豎屏切換等原因(V重啟生命週期),導致P重新建立,重新請求資料等資源消耗。(稍後詳述)

/**
 * cache:packageName + className(V) : Presenter
 */
private LinkedHashMap<String, BasePresenter> presenterCache = new LinkedHashMap<>();

目前對P的快取是對應互動業務邏輯,是按照UI的互動邏輯劃分的,也就是認為PV一 一對應(key:V的package + name; value:P),也就是實際上一個P中只註冊(快取)了一個V(eventTag)

優化目標(此處只提供建議,各位可自行優化擴充套件):

(1)P保持按照UI的互動邏輯劃分,PV實現一對多關係,實現對P的複用(key:P的package + name; value:P),P中將註冊(快取)多個V(eventTag),P與V互動的時候,會對所有快取的eventTag,都發送一遍EventMessage。

(2)P按照專案業務需求劃分,VP實現多對多關係,實現對P的真正複用(key:P的package + name; value:P)。

3.2. 契約類 Contract

契約類 Contract 來統一管理 mvp相關介面,使得某一功能模組的介面能更加直觀的呈現出來,這樣做是有利於後期維護的。

public class Contract {

    /**
     * @author 
     * @version 1.0
     */
    public interface IView {
        @Subscribe
        <E extends BaseEvent> void onEventMessageReceive(E event);
    }

    /**
     * @author 
     * @version 1.0
     */
    public interface IPresenter {
        void doInitProcess();
    }

    /**
     * @author
     * @version 1.0
     */
    public interface IModule {
    }

    /**
     * @author 
     * @version 1.0
     */
    public interface IPresenterManager {
        BasePresenter getPresenter(String localClassPath);

        void addPresenter(String localClassPath, BasePresenter presenter);
    }
}

3.3. V層

Base Library對ActivityFragment分別作了封裝,BaseActivity,BaseAppCompatActivity,BaseFragmentActivity分別對應Activity,AppCompatActivity,FragmentActivityBaseFragment,BaseFragmentV4分別對應 android.app.Fragment,android.support.v4.app.Fragment。

UI層的封裝沒啥可說的,大家的做法大同小異,僅供參考。

1. Activity

Base類分別做了以下幾件事情:

(1)把基礎行為封裝為模板

// 跟蹤列印當前activity名
LogUtils.i(getSimpleTag(), "sky_dreaming on onCreate activity = "
        + getSimpleTag());
// 載入佈局檔案
if (returnLayoutId() > 0) {
    this.setContentView(returnLayoutId());
    ButterKnife.bind(this);
}
// 初始化控制元件
initView();
// 特殊控制元件設定監聽器
setListener();
// 如果頁面不需要在onResume生命週期中重新整理資料,在onCreate中初始化載入資料;否則該行為放在onResume中執行
if (!refreshOnResume()) {
    /**
     * 初始化載入資料
     */
    initProcess();
}

(2)提供abstract方法供子類擴充套件

/**
 * Init views
 */
protected abstract void initView();
/**
 * Init data and refresh view
 * @param event BaseEvent
 * @param <E>   BaseEvent
 */
protected abstract <E extends BaseEvent> void initDataView(E event);
/**
 * receive and handle EventBus message
 * @param event BaseEvent
 * @param <E>   BaseEvent
 */
protected abstract <E extends BaseEvent> void onHandleMessage(E event);
/**
 * set listener to view
 */
protected abstract void setListener();
/**
 * get layout id
 * @return layout resource id
 */
protected abstract int returnLayoutId();
/**
 * create Presenter
 * @return P
 */
public abstract P createPresenter();
/**
 * if this view need EventBus
 * @return boolean
 */
protected abstract boolean needEventBus();

(3)開放Presenter註冊以及解注方法

由Application在Activity生命週期回撥方法中,呼叫registerPresenter()完成對P的建立和繫結以及解綁

@SuppressWarnings("unchecked")
public void registerPresenter() {
    if (needEventBus()) {
        registerEventBus();
    }
    mPresenter = (P) PresenterManager.getInstance().getPresenter(getSimpleTag());
    if (null == mPresenter) {
        mPresenter = createPresenter();
        PresenterManager.getInstance().addPresenter(getSimpleTag(), mPresenter);
    }
    mPresenter.registerViewEvent(getSimpleTag());
}

1)根據使用者需求,選擇是否註冊EventBus元件

2)從快取(PresenterManager)嘗試獲取presenter物件,如果獲取不到,建立一個,同時將新建立的物件納入快取。

3)把當前UI執行緒的標識TAG註冊給P(PV通過EventBus通訊,TAG用於區分目的UI執行緒)。

同時將建立P的方法createPresenter();開放給子類使用者實現。

解綁:unRegisterPresenter();

public void unregisterPresenter() {
    if (null != mPresenter) {
        mPresenter.unRegisterViewEvent(getSimpleTag());
    }
    unregisterEventBus();
}

(4)開放通用行為

統一接收Event訊息,並通過eventTag過濾,通過eventId分發

@Subscribe
@Override
public <E extends BaseEvent> void onEventMessageReceive(E event) {
    if (null == event || !event.eventTag.equals(getSimpleTag())) {
        return;
    }
    switch (event.actionId) {
        case BaseEvent.INIT_PROCESS_ACTION_ID:
            // do sth init view
            initDataView(event);
            break;
        default:
            onHandleMessage(event);
            break;
    }
}

獲取當前activity標識(包名 + 類名)

public String getSimpleTag() {
    return getPackageName() + this.getClass().getSimpleName();
}

跳轉到指定頁面

public void startNextActivity (Intent intent, boolean needForResult,
                               int requestCode, int enterAnim, int exitAnim, boolean needFinishCurrent) {
    if (needForResult) {
        startActivityForResult(intent, requestCode);
    } else {
        startActivity(intent);
    }
    if (enterAnim > 0 && exitAnim > 0) {
        overridePendingTransition(enterAnim, exitAnim);
    }
    if (needFinishCurrent) {
        finish();
    }
}

3.3.2. Fragment

Fragment在上述Activity封裝策略的基礎上,加了懶載入機制:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    /**
     *  (for lazy loading data)
     */
    isViewInitiated = true;
    prepareRequestData();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    /**
     *  (for lazy loading data)
     */
    prepareRequestData();
}
/**
 * prepare to get data (for lazy loading data)
 *
 * @return
 */
public boolean prepareRequestData() {
    // set param true: force update data when fragment visible
    return prepareRequestData(false);
}
/**
 * prepare to get data (for lazy loading data)
 *
 * @param forceUpdate true: force update data when fragment visible
 * @return
 */
public boolean prepareRequestData(boolean forceUpdate) {
    if (getUserVisibleHint() && isViewInitiated && (!isDataLoaded || forceUpdate)) {
        initProcess();
        isDataLoaded = true;
        return true;
    }
    return false;
}

3.4. P層

3.4.1. Presenter

(1)BasePresenter

Presenter對應互動業務邏輯,是按照UI的互動邏輯劃分的(當前PV一對一設計)。

P持有V的唯一標識(包名 + 類名)的快取列表(當前每個P只快取一個V的標識),通過新增,移除V標識,實現在P對V的註冊解注。P通過EventBus傳送帶有V唯一標識的Event訊息給V,V通過識別唯一標識來判斷接收到的訊息歸屬。

定義了V唯一標識的快取列表

/**
 * cache event tag
 */
private List<String> eventTagCache = new ArrayList<>();

提供了註冊,解注的開放介面

/**
 * create relationship with view
 * @param eventTag event tag
 */
public void registerViewEvent(String eventTag) {
    if (!isViewRegistered(eventTag)) {
        validTime = System.currentTimeMillis();
        eventTagCache.add(eventTag);
    }
}
/**
 * detach the relationship
 */
public void unRegisterViewEvent(String eventTag) {
    if (isViewRegistered(eventTag)) {
        eventTagCache.remove(eventTag);
    }
    if (eventTagCache.size() == 0) {
        invalidTime = System.currentTimeMillis();
    }
}

並內建本身失效策略,為外部對P的快取提供策略依據。

    /**
     * time for registering new event tag of view
     */
    private long validTime = 0;
    /**
     * time for clear new event tag of view
     */
    private long invalidTime = 0;
    public boolean isEffective() {
        return (invalidTime - validTime) / 1000 < PRESENTER_CACHE_TIME;
    }

提供傳送EventMessage訊息介面

public <E extends BaseEvent> void postEvent(E event) {
    EventBus.getDefault().post(event);
}

public <E extends BaseEvent> void postStickyEvent(E event) {
    EventBus.getDefault().postSticky(event);
}

(2)PresenterManager

P快取管理類,內建快取池,開放get,add介面,同時在每次get呼叫之前,輪詢檢查快取,剔除無效快取。

之所以設計Presenter快取策略,主要考慮兩點因素,一是對多V複用,二是節省資源,避免由於V生命週期異常等原因,導致P重構,浪費資源。之前有考慮把P的生成,P對V的註冊,解注也放到管理類中實現,後來取消了,有心者可以嘗試變更。

public class PresenterManager implements Contract.IPresenterManager {
    /**
     * cache
     */
    private LinkedHashMap<String, BasePresenter> presenterCache = new LinkedHashMap<>();
    
    // ......
     
    /**
     * @param localClassPath packageName + className
     * @return BasePresenter
     */
    public BasePresenter getPresenter(String localClassPath) {
        /*
         * clear Invalid presenter
         */
        for (Map.Entry<String, BasePresenter> entry : presenterCache.entrySet()) {
            if (null == entry.getKey() || null == entry.getValue()) {
                presenterCache.remove(entry.getKey());
                continue;
            }
            if (!entry.getValue().isEffective() && !entry.getKey().equals(localClassPath)) {
                presenterCache.remove(entry.getKey());
            }
        }
        if (presenterCache.containsKey(localClassPath)) {
            return presenterCache.get(localClassPath);
        } else {
            return null;
        }
    }
    /**
     * @param localClassPath packageName + className
     * @param presenter      BasePresenter
     */
    public void addPresenter(String localClassPath, BasePresenter presenter) {
        if (null == localClassPath || null == presenter) {
            return;
        }
        presenterCache.put(localClassPath, presenter);
    }
    // ......
}

3.4.2. Event

Event包提供了EventMessage的基類BaseEvent,定義了eventTag,eventId關鍵欄位,用於區分UI執行緒以及業務操作。BaseDataEvent增加了對Data資料的承載,用於需要傳輸資料的場景。

按照計劃,App所有與mvp相關的訊息體,都會繼承BaseEvent或者BaseDataEvent,為UI執行緒統一接收訊息提供支援,可以大大減少EventMessage類的定義數量,簡化程式碼。

public class BaseEvent {
    /**
     * default action id for Initialization UI thread
     */
    public static final int INIT_PROCESS_ACTION_ID = 20181001;
    /**
     * for different UI thread. default value: name of current class
     */
    public String eventTag;
    /**
     * same UI thread, different action
     */
    public int actionId = INIT_PROCESS_ACTION_ID;
    
    // ......
}
public class BaseDataEvent<T> extends BaseEvent {

    public T data;

    public BaseDataEvent() {
        super();
    }

    public BaseDataEvent(String eventTag) {
        super(eventTag);
    }
}

3.5. M層

Module對應業務資料管理,是按照資料業務劃分的(一個Module對應並管理多個Model(資料Bean,可以理解為介面,網路介面,資料庫介面等))。

無論對於功能型mvp架構(mvp作為頂層節點,每個M,V,P中進行業務模組劃分)而言,還是對於業務型mvp架構(業務模組作為頂層節點,每個業務節點中做mvp層次劃分)而言,Module就是P的資料管理員(按業務模組劃分),P管理業務,Module管理資料,至於Module把業務中涉及到的資料(Model)存到remote還是local,P並不關心。Module管理當前業務模組中各個Model(Bean)的儲存;Repository負責對資料在物件與儲存介質之間進行校驗,封裝,轉換(可有可無)。

結構說明:P ——> Module ->(Repository ->)(LoginModel –> net,RegisterModel -> local)

Module將被設計為資料儲存層(Model)向上層業務邏輯層(Presenter)提供服務的入口(外觀)。並負責協調Data Repository,管理並加工業務資料。

Base Library對Module的封裝比較簡單,按照MP以介面呼叫及回撥的設計思想,BaseModule做了如下封裝:

(1)快取資料回撥Observers

/**
 * model callback observer
 */
private Map<Class, IModelObserver> modelChangeObserver;

說明一下:資料回撥的Observer是針對Model(資料)的,不是針對P的,所以一個P中可能會向Module註冊多個Observer用於接收不同的型別的Model。

(2)對P回撥介面的註冊解注:

    /**
     * add
     *
     * @param modelClass    model class
     * @param modelObserver observer
     */
    public <T> BaseModule addModelObserver(Class<T> modelClass, IModelObserver modelObserver) {
        if (null == modelChangeObserver) {
            modelChangeObserver = new HashMap<>();
        }

        if (!modelChangeObserver.containsKey(modelClass)) {
            modelChangeObserver.put(modelClass, modelObserver);
        }
        return this;
    }

    /**
     * remove
     *
     * @param modelClass model class
     */
    public <T> void removeModelObserver(Class<T> modelClass) {
        if (modelChangeObserver.containsKey(modelClass)) {
            modelChangeObserver.remove(modelClass);
        }
    }

P中初始化Module時,根據P負責處理的業務,把對應不同Model(資料)的回撥介面註冊給Module。

(3)按照Model型別做資料回撥

    /**
     * call the notify method with model data
     *
     * @param modelClass model class
     * @param models     data
     */
    @SuppressWarnings("unchecked")
    public <T> void notifyModelObserver(Class<T> modelClass, T... models) {
        if (modelChangeObserver.containsKey(modelClass)) {
            modelChangeObserver.get(modelClass).onNotify(models);
        }
    }

Module子類中,針對業務需求擴充套件獲取Model(資料)的方法,獲取Model(資料)後,呼叫notifyModelObserver方法把資料回傳給P。

(4)定義資料回撥介面

    /**
     * @author Created by qiang.hou on 2018/5/9.
     * @version 1.0
     */
    public interface IModelObserver<T> {
        void onNotify(T... data);
    }

4,GlobalField

靜態全域性引數,預設配置引數等,不做贅述

public class GlobalField {
    public static final String SHARED_PREFERENCE_NAME = "default_shared_preference";

    public static final long PRESENTER_CACHE_TIME = 20;
}

總結

Base Library是一個android庫,也是一個完整的android工程,其他主工程app1,app2,app3需要新增Base Library工程依賴。

mvp是一種設計思想,致力於層級解耦,但它也只是一種架構思想,具體實現不應被mvp固定模式所束縛。

Base Library可優化的方向(僅供參考)

1,按照業務邏輯而非UI邏輯劃分P,實現PV多對多,實現對P的充分複用。

2,Module與Model之間,增加Repository,用於對原始資料(remote,localDB)的業務性加工處理。

3,放大EventBus訊息機制的使用範圍,目前只用於P—>V業務回撥部分。

 

最後,好搶手是子彈喂出來的,好coding是程式碼練出來的,Lib中涉及到的關鍵程式碼(基本上是所有)都已貼出,真正有興趣的不妨整理優化一下,歡迎交流心得體會。