Android MVP设计架构简单实现,其实就是为了以后编写代码的时候能偷懒。
1. 什么是MVP
MVP是相对MVC而言的。
MVP代表Model,View和Presenter。
View层负责处理用户事件和视图部分的展示。在Android中,它可能是Activity或者Fragment类。
Model层负责访问数据。数据可以是远端的Server API,本地数据库或者SharedPreference等。
Presenter层是连接(或适配)View和Model的桥梁。
MVC与MVP的区别
MVC:
Activity不仅要显示UI,还担任了一部分Controller的职责。
请求的业务代码往往被丢到了Activity里面,布局文件只能提供默认的UI设置,所以开发中视图层的变化也被丢到了Activity里面。
Activity本身承担着控制层的责任。所以Activity就成了MVC的集合,代码严重耦合,维护的成本也越来越高。
Model&View&Controller之间是可以相互作用的,造成严重的代码耦合。
MVP:
MVP与MVC最大的不同,其实是Activity职责的变化,由原来的C(控制层)变成了V(视图层),不再管控制层的问题,只管如何去显示。
控制层的角色就由我们的新人Presenter来担当,这种架构就解决了Activity过度耦合控制层和视图层的问题。
2. MVP实践
2.1 定义契约接口
IContract主要是为了管理View和Model接口,这在你需要编写多个View和Model时非常有用。
我们可以根据需要定义多个契约类,扩展IBaseView和IBaseModel接口以满足实际需求。
/**
* DESC:契约类,用于管理view和model。
* 实现的view和model需要继承实现其中的接口
*
* Created by ZhangShuai on 2017/12/11.
*/
public interface IContract {
interface IBaseView {
void showLoading();
void hideLoading();
//.....定义其它一些共用的接口
}
interface IBaseModel {
//.....定义一些共用的接口
}
}
2.2 定义BasePresenter
IBasePresenter
BasePresenter在设计时考虑了RxJava。
为了防止出现内存泄露,考虑了注销信息接口。
/**
* DESC:基础presenter接口
*
* Created by ZhangShuai on 2017/12/11.
*/
public interface IBasePresenter {
//Activity关闭把view对象置为空
void detach();
//将网络请求的每一个disposable添加进入CompositeDisposable,再退出时候一并注销
void addDisposable(Disposable subscription);
//注销所有请求
void unDisposable();
}
BasePresenter
/**
* DESC: 主要是用于添加、删除view,防止内存泄露。
* Created by ZhangShuai on 2017/12/11.
*/
public class BasePresenter 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
*
* Created by ZhangShuai on 2017/12/11.
*/
public abstract class BaseActivity
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. 实战
我们以一个登录页面作为实战的例子。
3.1 定义契约类ILoginContract
/**
* DESC:LoginContract
*
* 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 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 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 {
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() {
@Override
public void accept(UserInfo userInfo) throws Exception {
mModel.saveUserInfo(userInfo);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber() {
@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 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的结构实现起来相对简单,且大家在生活中经常用到,相信通过本文章,你能更加的深入了解MVP的大致结构和框架,并在实际开发中应用起来。