Android MVP設計架構簡單實現(xiàn),其實就是為了以后編寫代碼的時候能偷懶。
1. 什么是MVP
MVP是相對MVC而言的。
MVP代表Model,View和Presenter。
View層負責處理用戶事件和視圖部分的展示。在Android中,它可能是Activity或者Fragment類。
Model層負責訪問數(shù)據(jù)。數(shù)據(jù)可以是遠端的Server API,本地數(shù)據(jù)庫或者SharedPreference等。
Presenter層是連接(或適配)View和Model的橋梁。
MVC與MVP的區(qū)別
MVC:
- Activity不僅要顯示UI,還擔任了一部分Controller的職責。
- 請求的業(yè)務代碼往往被丟到了Activity里面,布局文件只能提供默認的UI設置,所以開發(fā)中視圖層的變化也被丟到了Activity里面。
- Activity本身承擔著控制層的責任。所以Activity就成了MVC的集合,代碼嚴重耦合,維護的成本也越來越高。
- Model&View&Controller之間是可以相互作用的,造成嚴重的代碼耦合。
MVP:
MVP與MVC最大的不同,其實是Activity職責的變化,由原來的C(控制層)變成了V(視圖層),不再管控制層的問題,只管如何去顯示。
控制層的角色就由我們的新人Presenter來擔當,這種架構就解決了Activity過度耦合控制層和視圖層的問題。
2. MVP實踐
2.1 定義契約接口
IContract主要是為了管理View和Model接口,這在你需要編寫多個View和Model時非常有用。
我們可以根據(jù)需要定義多個契約類,擴展IBaseView和IBaseModel接口以滿足實際需求。
/**
* DESC:契約類,用于管理view和model。
* 實現(xiàn)的view和model需要繼承實現(xiàn)其中的接口
* <p>
* Created by ZhangShuai on 2017/12/11.
*/
public interface IContract {
interface IBaseView {
void showLoading();
void hideLoading();
//.....定義其它一些共用的接口
}
interface IBaseModel {
//.....定義一些共用的接口
}
}
2.2 定義BasePresenter
IBasePresenter
BasePresenter在設計時考慮了RxJava。
為了防止出現(xiàn)內(nèi)存泄露,考慮了注銷信息接口。
/**
* DESC:基礎presenter接口
* <p>
* Created by ZhangShuai on 2017/12/11.
*/
public interface IBasePresenter {
//Activity關閉把view對象置為空
void detach();
//將網(wǎng)絡請求的每一個disposable添加進入CompositeDisposable,再退出時候一并注銷
void addDisposable(Disposable subscription);
//注銷所有請求
void unDisposable();
}
BasePresenter
/**
* DESC: 主要是用于添加、刪除view,防止內(nèi)存泄露。
* Created by ZhangShuai on 2017/12/11.
*/
public class BasePresenter<V extends IContract.IBaseView, M extends IContract.IBaseModel> implements IBasePresenter {
CompositeDisposable mSubscriptions;
protected V mView;
protected M mModel;
public BasePresenter(V view) {
mView = view;
}
protected void attach(M model) {
this.mModel = model;
}
@Override
public void detach() {
if (this.mView != null) {
mView = null;
}
unDisposable();
}
@Override
public void addDisposable(Disposable subscription) {
mSubscriptions.add(subscription);
}
@Override
public void unDisposable() {
if (mSubscriptions.isDisposed() == false) {
mSubscriptions.dispose();
}
}
}
2.3 定義BaseActivity
/**
* DESC: MVP BaseActivity
* <p>
* Created by ZhangShuai on 2017/12/11.
*/
public abstract class BaseActivity<P extends BasePresenter>
extends AppCompatActivity implements IContract.IBaseView {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = initPresenter();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mPresenter != null) {
mPresenter.detach();
mPresenter = null;
}
}
// 構造實際所需的prensenter
public abstract P initPresenter();
}
3. 實戰(zhàn)
我們以一個登錄頁面作為實戰(zhàn)的例子。
3.1 定義契約類ILoginContract
/**
* DESC:LoginContract
* <p>
* Created by ZhangShuai on 2017/12/11.
*/
public class ILoginContract {
interface ILoginView extends IContract.IBaseView {
// 顯示信息
void showMsg(String msg);
}
interface ILoiginModel extends IContract.IBaseModel {
// 登錄接口
Flowable<UserInfo> login(String name, String pwd);
void saveUserInfo(UserInfo info);
}
}
ILoginContract使得我們設計的接口一目了然。
3.2 定義Model類
class LoginModel implements ILoginContract.ILoiginModel {
private static String BASE_URL = "xxxxx";
// 結合Retrofit和RxJava完成登錄
@Override
public Flowable<UserInfo> login(String name, String pwd) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL).
addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
MyService api = retrofit.create(MyService.class);
return api.login(name, pwd);
}
@Override
public void saveUserInfo(UserInfo info) {
// 保存用戶信息
}
}
3.3 定義Presenter
class LoginPresenter extends
BasePresenter<ILoginContract.ILoginView, ILoginContract.ILoiginModel> {
public LoginPresenter(ILoginContract.ILoginView view) {
super(view);
LoginModel model = new LoginModel();
attach(model);
}
public void login(String name, String pwd) {
mView.showLoading();
mModel.login(name, pwd)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<UserInfo>() {
@Override
public void accept(UserInfo userInfo) throws Exception {
mModel.saveUserInfo(userInfo);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<UserInfo>() {
@Override
public void onSubscribe(Subscription s) {
}
@Override
public void onNext(UserInfo userInfo) {
mView.showMsg("Login Successful.");
}
@Override
public void onError(Throwable t) {
mView.showMsg("Login fail.");
mView.hideLoading();
}
@Override
public void onComplete() {
mView.hideLoading();
}
});
}
}
3.4 定義View
其實就是Activity
public class DemoActivity extends BaseActivity<LoginPresenter> implements ILoginContract.ILoginView {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
}
@Override
protected void onResume() {
super.onResume();
mPresenter.login("213", "456");
}
@Override
public LoginPresenter initPresenter() {
return new LoginPresenter(DemoActivity.this);
}
@Override
public void showMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
@Override
public void showLoading() {
//顯示進度框
}
@Override
public void hideLoading() {
//隱藏進度框
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
4. 總結
在簡單的設計中,MVP的代碼看起來有些復雜和冗余,但是隨著APP的功能不斷豐富,MVP將是你的不二選擇。
MVP的結構實現(xiàn)起來相對簡單,且大家在生活中經(jīng)常用到,相信通過本文章,你能更加的深入了解MVP的大致結構和框架,并在實際開發(fā)中應用起來。