系列文章:
1-準(zhǔn)備工作
2-搭建項目框架
3-功能實現(xiàn)
4-加入網(wǎng)絡(luò)緩存
請先閱讀MVP架構(gòu)實現(xiàn)的Github客戶端(1-準(zhǔn)備工作). 本文承接上文, 主要介紹項目框架搭建.
廢話少說, 放碼過來
1, 提取一個mvp模塊
提取MVP中View/Presenter相關(guān)接口到一個獨立的mvp模塊(可復(fù)用):
包結(jié)構(gòu)

類圖

簡單說明
一個MvpView接口來約束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ù), 在此擴展了一個通用的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框架方面, 個人主張是先基于MVP架構(gòu)分包 然后根據(jù)業(yè)務(wù)功能劃分模塊的, 如下:

其中:
-
common
- 包含util, config, constant等通用包和類.
-
data
- 包含model, api, db, pref, 網(wǎng)絡(luò)接口實現(xiàn)等.
- 其中對外公開一個DataRepository提供業(yè)務(wù)接口相關(guān)數(shù)據(jù).
-
di
- 依賴注入相關(guān)的類.
- 根據(jù)dagger2的風(fēng)格, 一般有module和component模塊.
-
presenter
- 里面根據(jù)業(yè)務(wù)模塊劃分.
-
ui
- 包含UI層的所有東東. activity, fragment, widget, dialog, adapter等, 根據(jù)需求不同分包方式有出入.
層次結(jié)構(gòu)
層次結(jié)構(gòu)相對與業(yè)務(wù)需求而言, 例如賬戶相關(guān)的登錄注冊, repo模塊相關(guān)的repo列表, 詳情等...
大體上每個業(yè)務(wù)模塊都會由以下幾個部分構(gòu)成, 整體的項目層次也是如此:

3, 完善基礎(chǔ)工程
根據(jù)上述兩步, 一個項目的基本架構(gòu)已經(jīng)完成, 但是并不完整, 我們還需要添加一些通用類, 基礎(chǔ)類來完善下. 其實這些基類也相當(dāng)于是一個編碼規(guī)范, 特別是多人合作項目中, 提前根據(jù)項目需求寫一些通用類, 工具類, 基類等, 能夠避免后續(xù)大家編碼上各自一套. 所以個人認(rèn)為這些類的編寫也屬于搭建框架的一部分.
添加相關(guān)Base類
為了便于統(tǒng)一處理, 慣例, 我們需要為Activity, Fragment創(chuàng)建一個BaseActivity, BaseFragment. 可以在ui包里創(chuàng)建一個base子包放置.

這個基類好處多多, 例如我們對界面的統(tǒng)一處理, 生命周期的日志打印, 添加統(tǒng)計工具等, 都能很方便的再基類里面處理.
封裝相關(guān)工具類
如上文所說, 個人習(xí)慣對第三方開源庫再做一層封裝, 以便后續(xù)靈活替換.
使用過程中, 也只需調(diào)用封裝后的接口即可, 無需關(guān)注具體的依賴包. 也利于大家協(xié)作統(tǒng)一.
例如:
- Logger封裝
創(chuàng)建一個AppLog類來包裝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);
}
}
- 圖片加載庫封裝
封裝一個ImageLoader工具類來對外提供接口加載圖片:
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ǔ)類
因為我們使用的Dagger2來做依賴注入, 因為Activity和Application的Context是比較常用的, 我們會構(gòu)建Activity, Application相關(guān)的component/module來提供對應(yīng)的Context.
具體代碼參看github工程源碼.
4, 整體結(jié)構(gòu)
假設(shè)我們的產(chǎn)品需要是迭代式的, 至此, 我們的基礎(chǔ)框架已經(jīng)差不多了(不建議做過多過早設(shè)計).
回顧下, 大體結(jié)構(gòu)現(xiàn)在基本如下:
mvp

app

具體代碼請參看https://github.com/mingjunli/GithubApp
目前代碼只是一個基礎(chǔ)的框架, 心急的同學(xué)可以參看這個工程, 架構(gòu)類似. 一個簡單的新聞客戶端, 用來做MVP demo的.