准备用MVP框架搭建一个自己的项目,之前的项目有用到过,但都是公司的同事搭建好的,现在自己搭建一个。
搭建之前先来了解一下MVP。
1、什么是MVP
M(Model)负责数据的请求,解析,过滤等数据操作。
V(View)负责处理UI,通常以Activity Fragment的形式出现。
P(Presenter)View Model中间件,交互的桥梁。
2、MVP的优点
分离了UI逻辑和业务逻辑,降低了耦合。
Activity只处理UI相关操作,代码变得更加简洁。
UI逻辑和业务逻辑抽象到接口中,方便阅读及维护。
把业务逻辑抽到Presenter中去,避免复杂业务逻辑造成的内存泄漏。
3、MVP与MVC的比较
MVP的优点:
1)复杂的逻辑处理放在presenter进行处理,减少了activity的臃肿。
2)M层与V层完全分离,修改V层不会影响M层,降低了耦合性。
3)可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。
3)P层与V层的交互是通过接口来进行的,便于单元测试。
MVP的缺点:
由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁,视图需要改变,一般presenter也需要跟着改变.
/******************************************************************************************************************/
MVC的优点:
1):分工明确,各司所职。
2):一定程度上降低了代码间的耦合性。
MVC的缺点:
1):随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
2):视图和控制器间过于紧密的联系,妨碍了各自的重用。
搭建过程
创建基类
1.对View进行封装,主要处理显示加载框、请求成功、请求失败等操作
package com.lyw.modulemvp.base;
import android.content.Context;
/**
* 功能描述:
* Created on 2020/6/29.
* @author lyw
*/
public interface IBaseView {
/**
* 显示加载框
*/
void showLoading();
/**
* 隐藏加载框
*/
void dismissLoading();
/**
* 空数据
*
* @param tag TAG
*/
void onEmpty(Object tag);
/**
* 错误数据
*
* @param tag TAG
* @param errorMsg 错误信息
*/
void onError(Object tag, String errorMsg);
/**
* 上下文
*
* @return context
*/
Context getContext();
}
2.对Presenter封装 ,为了避免持有View的Presenter做耗时操作而引起的内存泄漏,我们的Presenter应该和宿主Activity/Fragment同创建、同销毁。
package com.lyw.modulemvp.base;
import android.content.Context;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 功能描述:
* Created on 2020/6/29.
* @author lyw
*/
public abstract class BasePresenter<M extends IBaseModel, V extends IBaseView> {
private V mView;
private M mModel;
private WeakReference<V> weakReference;
/**
* 绑定View
*/
@SuppressWarnings("unchecked")
public void attachView(V view) {
weakReference = new WeakReference<>(view);
mView = (V) Proxy.newProxyInstance(
view.getClass().getClassLoader(),
view.getClass().getInterfaces(),
new MvpViewHandler(weakReference.get()));
if (this.mModel == null) {
this.mModel = createModule();
}
}
/**
* 解绑View
*/
public void detachView() {
this.mModel = null;
if (isViewAttached()) {
weakReference.clear();
weakReference = null;
}
}
/**
* 是否与View建立连接
*/
protected boolean isViewAttached() {
return weakReference != null && weakReference.get() != null;
}
protected V getView() {
return mView;
}
protected M getModule() {
return mModel;
}
protected Context getContext() {
return getView().getContext();
}
protected void showLoading() {
getView().showLoading();
}
protected void dismissLoading() {
getView().dismissLoading();
}
/**
* 通过该方法创建Module
*/
protected abstract M createModule();
/**
* 初始化方法
*/
public abstract void start();
/**
* View代理类 防止 页面关闭P异步操作调用V 方法 空指针问题
*/
private class MvpViewHandler implements InvocationHandler {
private IBaseView mvpView;
MvpViewHandler(IBaseView mvpView) {
this.mvpView = mvpView;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果V层没被销毁, 执行V层的方法.
if (isViewAttached()) {
return method.invoke(mvpView, args);
} //P层不需要关注V层的返回值
return null;
}
}
}
3、对Activity的封装,Fragment封装同理,通过泛型规定Presenter,并且暴露抽象方法createPresenter()给子类来创建Presenter,基类实现BaseView中的公共方法,减少子类代码的冗余。
package com.lyw.modulemvp.base;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
/**
* 功能描述:Mvp Activity基类
* Created on 2020/6/29.
* @author lyw
*/
public abstract class BaseMvpActivity<P extends BasePresenter> extends BaseActivity implements IBaseView {
protected P presenter;
private Context mContext;
@SuppressWarnings("unchecked")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建present
presenter = createPresenter();
if (presenter != null) {
presenter.attachView(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.detachView();
presenter = null;
}
}
@Override
public void showLoading() {
if (mLoadingLayout != null) {
mLoadingLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void dismissLoading() {
if (mLoadingLayout != null) {
mLoadingLayout.setVisibility(View.GONE);
}
}
@Override
public void onEmpty(Object tag) {
}
@Override
public void onError(Object tag, String errorMsg) {
}
@Override
public Context getContext() {
return mContext;
}
/**
* 创建Presenter
*/
protected abstract P createPresenter();
}
子类的具体实现会在后面的demo完善,DEMO地址