MVP架構(gòu)實(shí)現(xiàn)的Github客戶(hù)端(2-搭建項(xiàng)目框架)

系列文章:
1-準(zhǔn)備工作
2-搭建項(xiàng)目框架
3-功能實(shí)現(xiàn)
4-加入網(wǎng)絡(luò)緩存

請(qǐng)先閱讀MVP架構(gòu)實(shí)現(xiàn)的Github客戶(hù)端(1-準(zhǔn)備工作). 本文承接上文, 主要介紹項(xiàng)目框架搭建.

廢話(huà)少說(shuō), 放碼過(guò)來(lái)

1, 提取一個(gè)mvp模塊

提取MVP中View/Presenter相關(guān)接口到一個(gè)獨(dú)立的mvp模塊(可復(fù)用):

包結(jié)構(gòu)

mvp_package_structure

類(lèi)圖

mvp_class_diagram

簡(jiǎn)單說(shuō)明

一個(gè)MvpView接口來(lái)約束View組件:

public interface MvpView {
}

MvpPresenter接口中關(guān)聯(lián)MvpView:

public interface MvpPresenter<V extends MvpView> {


    /**
     * Set or attach the view to this presenter
     */
    @UiThread
    void attachView(V view);


    /**
     * Will be called if the view has been destroyed. Typically this method will be invoked from
     * <code>Activity.detachView()</code> or <code>Fragment.onDestroyView()</code>
     */
    @UiThread
    void detachView();


}

另外, 由于現(xiàn)在App的內(nèi)容展示大部分是基于網(wǎng)絡(luò)數(shù)據(jù), 在此擴(kuò)展了一個(gè)通用的LceView, Lce取Loading, Content, Error之意:

public interface LceView<M> extends MvpView {


    @UiThread
    public void showLoading();


    @UiThread
    public void dismissLoading();


    @UiThread
    public void showContent(M data);


    @UiThread
    public void showError(Throwable e);
}

2, 搭建app框架

包結(jié)構(gòu)

app框架方面, 個(gè)人主張是先基于MVP架構(gòu)分包 然后根據(jù)業(yè)務(wù)功能劃分模塊的, 如下:

app_package_structure

其中:

  • common

    • 包含util, config, constant等通用包和類(lèi).
  • data

    • 包含model, api, db, pref, 網(wǎng)絡(luò)接口實(shí)現(xiàn)等.
    • 其中對(duì)外公開(kāi)一個(gè)DataRepository提供業(yè)務(wù)接口相關(guān)數(shù)據(jù).
  • di

    • 依賴(lài)注入相關(guān)的類(lèi).
    • 根據(jù)dagger2的風(fēng)格, 一般有module和component模塊.
  • presenter

    • 里面根據(jù)業(yè)務(wù)模塊劃分.
  • ui

    • 包含UI層的所有東東. activity, fragment, widget, dialog, adapter等, 根據(jù)需求不同分包方式有出入.

層次結(jié)構(gòu)

層次結(jié)構(gòu)相對(duì)與業(yè)務(wù)需求而言, 例如賬戶(hù)相關(guān)的登錄注冊(cè), repo模塊相關(guān)的repo列表, 詳情等...
大體上每個(gè)業(yè)務(wù)模塊都會(huì)由以下幾個(gè)部分構(gòu)成, 整體的項(xiàng)目層次也是如此:


mvp_layer

3, 完善基礎(chǔ)工程

根據(jù)上述兩步, 一個(gè)項(xiàng)目的基本架構(gòu)已經(jīng)完成, 但是并不完整, 我們還需要添加一些通用類(lèi), 基礎(chǔ)類(lèi)來(lái)完善下. 其實(shí)這些基類(lèi)也相當(dāng)于是一個(gè)編碼規(guī)范, 特別是多人合作項(xiàng)目中, 提前根據(jù)項(xiàng)目需求寫(xiě)一些通用類(lèi), 工具類(lèi), 基類(lèi)等, 能夠避免后續(xù)大家編碼上各自一套. 所以個(gè)人認(rèn)為這些類(lèi)的編寫(xiě)也屬于搭建框架的一部分.

添加相關(guān)Base類(lèi)

為了便于統(tǒng)一處理, 慣例, 我們需要為Activity, Fragment創(chuàng)建一個(gè)BaseActivity, BaseFragment. 可以在ui包里創(chuàng)建一個(gè)base子包放置.


base_class

這個(gè)基類(lèi)好處多多, 例如我們對(duì)界面的統(tǒng)一處理, 生命周期的日志打印, 添加統(tǒng)計(jì)工具等, 都能很方便的再基類(lèi)里面處理.

封裝相關(guān)工具類(lèi)

上文所說(shuō), 個(gè)人習(xí)慣對(duì)第三方開(kāi)源庫(kù)再做一層封裝, 以便后續(xù)靈活替換.
使用過(guò)程中, 也只需調(diào)用封裝后的接口即可, 無(wú)需關(guān)注具體的依賴(lài)包. 也利于大家協(xié)作統(tǒng)一.
例如:

  1. Logger封裝
    創(chuàng)建一個(gè)AppLog類(lèi)來(lái)包裝Logger:
public class AppLog {

    private static final String TAG = "GithubApp";

    /**
     * initialize the logger.
     */
    public static void init() {
        Logger.init(TAG);
    }

    /**
     * log.i
     * @param msg
     */
    public static void i(String msg) {
        if (BuildConfig.DEBUG) {
            Logger.i(msg);
        }
    }

    /**
     * log.d
     * @param msg
     */
    public static void d(String msg) {
        if (BuildConfig.DEBUG) {
            Logger.d(msg);
        }
    }

    /**
     * log.w
     * @param msg
     */
    public static void w(String msg) {
        if (BuildConfig.DEBUG) {
            Logger.w(msg);
        }
    }

    /**
     * log.e
     * @param msg
     */
    public static void e(String msg) {
        Logger.e(msg);
    }
}
  1. 圖片加載庫(kù)封裝
    封裝一個(gè)ImageLoader工具類(lèi)來(lái)對(duì)外提供接口加載圖片:
public class ImageLoader {

    /**
     * Load image from source and set it into the imageView. Use Glide now.
     * @param context context.
     * @param source could be Uri/String/File/ResourceId.
     * @param view the imageView.
     */
    public static void load(Context context, Object source, ImageView view) {
        Glide.with(context)
                .load(source)
                .centerCrop()
                .into(view);
    }
}

Dagger相關(guān)基礎(chǔ)類(lèi)

因?yàn)槲覀兪褂玫腄agger2來(lái)做依賴(lài)注入, 因?yàn)锳ctivity和Application的Context是比較常用的, 我們會(huì)構(gòu)建Activity, Application相關(guān)的component/module來(lái)提供對(duì)應(yīng)的Context.
具體代碼參看github工程源碼.

4, 整體結(jié)構(gòu)

假設(shè)我們的產(chǎn)品需要是迭代式的, 至此, 我們的基礎(chǔ)框架已經(jīng)差不多了(不建議做過(guò)多過(guò)早設(shè)計(jì)).
回顧下, 大體結(jié)構(gòu)現(xiàn)在基本如下:

mvp

mvp

app

app

具體代碼請(qǐng)參看https://github.com/mingjunli/GithubApp

目前代碼只是一個(gè)基礎(chǔ)的框架, 心急的同學(xué)可以參看這個(gè)工程, 架構(gòu)類(lèi)似. 一個(gè)簡(jiǎn)單的新聞客戶(hù)端, 用來(lái)做MVP demo的.

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

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

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