本文基於MVP整理出了一套適合本身的架構php
該系列文章會不斷更新Android項目開發中一些好的架構和小技巧java
系列一 Android架構系列-基於MVP建立適合本身的架構
系列二 Android架構系列-如何優美的寫Intent
系列三 Android架構系列-開發規範
系列四 Android架構系列-封裝本身的okhttp
系列五 Android架構系列-MVP架構的實際應用android
MVP架構是當前比較成熟的Android架構,還有其餘架構好比最初始的MVC和MVVM。MVC相對於較爲落後,MVVM使用DataBind,普及性不如MVP。因此最終決定本身設計的框架是基於MVP思想進行總結的框架。git
選擇MVP框架的緣由之一也是google官方的示例中MVP sample已是完成,證實google官方對於MVP的認可度。github
官方項目地址:
github.com/googlesampl…api
一個較爲詳細的官方項目源碼解析的文章:
www.infoq.com/cn/articles…緩存
具體的MVP架構相關文章網上已經很是多了,具體的能夠自行查找。MVP的存在主要是因爲普通MVC架構會致使項目中activity過於臃腫,當項目愈來愈大後,代碼可讀性大大下降。服務器
MVP的思想是將activity做爲view層,只負責與xml的渲染和監聽事件,具體處理數據邏輯放到一個新定義的Present層。減小了activity負責的事情。而且能夠強迫開發者養成分模塊功能開發的思想。開發前設計好功能模塊,而不是像之前同樣寫流水帳同樣寫代碼。從頭寫到尾。網絡
本身根據MVP的思想和一些好的源碼總結了一套適合字的框架。真正的架構是依賴義務存在的,因此建議你們能總結出適合本身項目的代碼。架構
在目錄分配上決定採用根據功能模塊進行劃分,而不是全部activty在一個目錄的方法。相似google的例子:
緣由幾點:
具體例子分配以下:
Model層中又能夠分爲Api層和Cache層。
主要是網絡獲取數據信息等接口。
使用了本身二次封裝過的Retrofit+Okhttp+Gson組合。詳細能夠參見文章:www.jianshu.com/p/283d1a7a0…
示例SampleApi:
public class SampleApi extends BaseApi {
private static final String mBaseUrl = "http://192.168.3.1/";
private ApiStore mApiStore;
public SampleApi() {
super(mBaseUrl);
mApiStore = mRetrofit.create(ApiStore.class);
}
/** * 獲取xxx數據 * @param uid * @param callback */
public void getSampleInfo(String uid, ApiCallback<GetSampleInfoRet> callback) {
Call<GetSampleInfoRet> call = ((ApiStore)mApiStore).getSampleInfo(uid);
call.enqueue(new RetrofitCallback<GetSampleInfoRet>(callback));
}
public interface ApiStore {
@FormUrlEncoded
@POST("test_retrofit.php")
Call<GetSampleInfoRet> getSampleInfo(@Field("uid") String uid);
}
}複製代碼
本地緩存部分數據。
使用了ASimpleCache緩存開源代碼。詳細能夠參見文章:www.jianshu.com/p/25c107ed7…
示例SampleCache:
public class SampleCache extends BaseCache {
private final String KEY_NEWEST_SAMPLE_INFO = "sample_newest_info";
public SampleCache(Context context) {
super(context);
}
/** * 保存sample信息 * @param serializable */
public void saveNewestSample(Serializable serializable) {
mCache.put(KEY_NEWEST_SAMPLE_INFO, serializable);
}
/** * 獲取sample信息 * @return */
public SampleInfo getNewestSampleInfo() {
return (SampleInfo) mCache.getAsObject(KEY_NEWEST_SAMPLE_INFO);
}
/** * 移除緩存 */
public void removeNewestSampleInfo() {
mCache.remove(KEY_NEWEST_SAMPLE_INFO);
}
}複製代碼
實體化數據類。
Presenter層又能夠分爲Contract協議接口,和具體的Presenter處理
負責約定view層和presenter層的接口,view和presenter實現相應接口,最終達到解耦的目的。
SampleContract示例:
public interface SampleContract {
interface View {
void showSample(SampleInfo sampleInfo); //顯示sample
void errorGetSample(String msg); //顯示錯誤信息
}
interface Presenter {
void getNewestSample(); //獲取當前最新的xxx
}
}複製代碼
負責從model層獲取數據、整理數據、行爲處理等。處理後調用view顯示數據。
SamplePresenter示例:
public class SamplePresenter extends BasePresenter implements SampleContract.Presenter {
private SampleContract.View mView;
private SampleApi mApi;
private SampleCache mCache;
public SamplePresenter(SampleContract.View view) {
mView = view;
mApi = new SampleApi();
mCache = new SampleCache(GlobalApp.getInstance().getContext());
}
@Override
public void getNewestSample() {
//先從緩存獲取
SampleInfo sampleInfo = mCache.getNewestSampleInfo();
if(sampleInfo == null) {
//從網絡獲取
mApi.getSampleInfo("uid", new BaseApi.ApiCallback<GetSampleInfoRet>() {
@Override
public void onSuccess(GetSampleInfoRet ret) {
//緩存
mCache.saveNewestSample(ret.data);
//頁面顯示
mView.showSample(ret.data);
}
@Override
public void onError(int err_code, String err_msg) {
//服務端返回錯誤碼
mView.errorGetSample(err_msg);
}
@Override
public void onFailure() {
//網絡請求或者解析錯誤
mView.errorGetSample("服務器請求錯誤");
}
});
} else {
mView.showSample(sampleInfo);
}
}
}複製代碼
即平時所說的activity、fragment等。繼承自SampleContract的view接口,只負責UI相關顯示刷新等。因爲拉出了presenter層,view層的代碼變得極爲清晰
SampleActivity示例:
public class SampleActivity extends BaseActivity implements SampleContract.View {
@BindView(R.id.txtName)
TextView txtName;
@BindView(R.id.imgAvatar)
ImageView imgAvatar;
private SampleContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
ButterKnife.bind(this);
mPresenter = new SamplePresenter(this);
}
@Override
public void showSample(SampleInfo sampleInfo) {
txtName.setText(sampleInfo.sample_name);
Glide.with(this)
.load(sampleInfo.avatar)
.into(imgAvatar);
}
@Override
public void errorGetSample(String msg) {
//錯誤信息
}
}複製代碼
以上代碼Github地址:
github.com/tsy12321/Ba…
注:該項目會作成一個基礎的項目框架,包含各類封裝好的工具,底層庫和MVP架構,還在不斷更新中,歡迎關注提Issue!
更多文章關注個人公衆號