上個專案忙完了第一版,在此對上個專案的架構總結下,不斷總結分析,才能發現結構的短板,才能搭出屬於自己的最完美的架構。
1.分包
------我的分包如下圖:
adapter:放一些adapter類,屬於view層的api:放一些網路請求相關的類,如配置retrofit
base:放一些activity、fragment、presenter的基類
common:放一些全域性都會用到的公共類,如application
model:我的model層只放了bean類,分為request和response,跟傳統mvp的model不同,傳統mvp的model層是請求網路資料,然後p層拿到m層和v層的引用,使m層和v層互動,但那樣程式碼量太多了,每一個請求都要建立一個model類,為了簡介,我就把請求網路資料直接放在了p層,在後面的程式碼中你會看到。
presenter:放presenter類
utils:放一些工具類
viewinterface:放view介面類
viewimpl:放view實現類
widget:放自定義view
------因為這個專案不大,介面不多,所以我採用此種分包,如果專案功能模組比較多的話,按功能模組分包比較好,結構清晰。下圖是我之前做過的功能模組比較多的專案:
2.mvp
自2016年起,mvp框架一度興起,越來越多的安卓開發者都選擇用mvp框架來開發app。mvp結合rxjava和retrofit 簡直爽的不要不要的,自從用了mvp結合rxjava和retrofi,程式碼簡潔了,邏輯也清晰了,呼叫也優雅了,維護成本也低利了。公司的這個專案我是用mvp+rxjava2+retrofit2+butterknife。
此mvp框架用到了註解、工廠模式、代理模式來解決程式碼冗餘、記憶體洩露(P在請求網路資料時,view(Activity或者Fragment)介面銷燬,導致P仍然持有view的引用)、presenter生命週期以及資料儲存問題;通過泛型將view和presenter繫結,可在view中直接呼叫getPresenter()獲取presenter來請求網路資料,在presenter中可以直接通過呼叫getView()獲取view來更新介面。請求網路用的是封裝後的rxjava+retrofit,新增了網路請求和響應攔截器,網路請求和響應json可直接在在Android Studio中的Logcat中一目瞭然。
具體的原始碼實現我就不一一介紹了,感興趣的朋友可以下載原始碼,自行檢視;框架原始碼連結(https://github.com/isJoker/R2R2Mvp)3.使用
你的api
public interface WApi {
//獲取電影列表
@POST("/PageSubArea/TrailerList.api")
Flowable<MoiveListResponse> getMoiveList();
}
複製程式碼
首先,先定義一個view介面IMoiveListView
/**
* Created by JokerWan on 2017/12/11.
* WeChat: wjc398556712
* Function:
*/
public interface IMoiveListView extends IWanBaseView{
void onLoading();
void onLoadSucess(MoiveListResponse moiveListResponse);
void onLoadFail(String msg);
}
複製程式碼
Activity的使用(Fragment的使用類似),通過註解 @CreatePresenter建立Presenter
/**
* Created by JokerWan on 2017/12/11.
* WeChat: wjc398556712
* Function:
*/
@CreatePresenter(MoiveListPresenter.class)
public class MainActivity extends AWanBaseActivity<IMoiveListView,MoiveListPresenter>
implements IMoiveListView {
@BindView(R.id.tv_moive_name)
TextView tvMoiveName;
@BindView(R.id.img_moive)
ImageView imgMoive;
@Override
public int getViewLayoutId() {
return R.layout.activity_main;
}
@Override
public void initData(Bundle savedInstanceState) {
if (null != savedInstanceState) {
// TODO: 2017/12/11 資料恢復
}
getPresenter().getMoiveList();
}
@Override
public void onLoading() {
tvMoiveName.setText("資料載入中,請稍後...");
}
@Override
public void onLoadSucess(MoiveListResponse moiveListResponse) {
MoiveListResponse.TrailersBean trailersBean = moiveListResponse.getTrailers().get(1);
tvMoiveName.setText(trailersBean.getMovieName());
Glide
.with(this)
.load(trailersBean.getCoverImg())
.into(imgMoive);
}
@Override
public void onLoadFail(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
複製程式碼
presenter的使用
/**
* Created by JokerWan on 2017/12/11.
* WeChat: wjc398556712
* Function:
*/
public class MoiveListPresenter extends AWanBasePresenter<IMoiveListView> {
public void getMoiveList(){
getView().onLoading();
wApi.getMoiveList()
.compose(ApiUtils.getScheduler())
.subscribe(new ApiSubscriber<MoiveListResponse>() {
@Override
public void onNext(MoiveListResponse moiveListResponse) {
if(moiveListResponse != null) {
getView().onLoadSucess(moiveListResponse);
}
}
@Override
public void onError(Throwable t) {
getView().onLoadFail(t.getMessage());
}
});
}
}
複製程式碼
4.demo執行後的效果