AndroidMVP框架搭建
前⾔
本⽂主要根据⾃⾝项⽬的使⽤和对MVP的理解,搭建符合⾃⾝项⽬情况的MVP架构。
关于MVP
M(Model)负责数据的请求,解析,过滤等数据操作
V(View)负责处理UI,通常以Activity Fragment的形式出现。
P(Presenter)View Model中间件,交互的桥梁。
MVP的好处
分离了UI逻辑业务逻辑,降低了耦合。
Activity只处理UI相关操作,代码变得更加简洁。
UI逻辑和业务逻辑抽象到接⼝中,⽅便阅读及维护。
把业务逻辑抽到Presenter中去,避免复杂业务逻辑造成的内存泄漏。
具体实现
1.view
IView:⼀般情况下,做数据请求都有显⽰加载框、请求成功、请求失败等操作,我们把这些共有的功能封装到IView中。
public interface IView {
/**
* 显⽰加载框
*/
void showLoading();
/**
* 隐藏加载框
*/
void dismissLoading();
/**
* ⽹络请求失败
*
* @param ex  异常信息
* @param code 错误码
* @param msg  错误信息
*/
void onFail(Throwable ex, String code, String msg);
/**
* ⽹络错误
*/
void onNetError();
}
2.Presenter
IPresenter:为了避免持有View的Presenter做耗时操作⽽引起的内存泄漏,我们的Presenter应该和宿主Activity/Fragment⽣命周期绑定。
public interface IPresenter<T extends IView> {
/**
* 绑定view
* @param view view
*/
void attachView(T view);
/**
* 分离view
*/
void detachView();
/**
* 判断view是否已经销毁
* @return true 未销毁
*/
boolean isViewAttach();
}
BasePresenter:抽象的persenter业务处理层。关联抽象层view和抽象model。
public abstract class BasePresenter<T extends IView, K extends IModel> implements IPresenter<T> {    protected K mModel;
private WeakReference<T> weakReference;
@Override
public void attachView(T view) {
// 使⽤弱引⽤持有view对象,防⽌内存泄漏
weakReference = new WeakReference<>(view);
if (this.mModel == null) {
this.mModel = createModule();
}
}
@Override
public void detachView() {
if (isViewAttach()) {
weakReference.clear();
weakReference = null;
}
if (mModel != null) {
mModel.unSubscribe();
mModel = null;
}
}
@Override
public boolean isViewAttach() {
return weakReference != null && () != null;
}
protected T getView() {
();
}
protected void showLoading() {
if (isViewAttach()) {
getView().showLoading();
}
}
protected void onFail(Throwable ex, String code, String msg) {
if (isViewAttach()) {
getView().onFail(ex, code, msg);
}
}
protected void onNetError() {
if (isViewAttach()) {
getView().onNetError();
}
}
protected void dismissLoading() {
if (isViewAttach()) {
getView().dismissLoading();
}
}
/**
* 由外部创建 module
*
* @return module
*/
protected abstract K createModule();
}
IModel:由于项⽬使⽤Rxjava+Retrofit2.0+Okhttp,所以我在model层对Rxjava进⾏绑定和解绑,防⽌内存泄漏。
public interface IModel {
void unSubscribe();
void addSubscribe(Subscription subscription);
}
BaseModel:实现对Rxjava绑定和解绑,初始化ApiService。
public class BaseModel implements IModel {
protected ApiService mApi;
private CompositeSubscription mCompositeSubscription;
public BaseModel() {
this.mApi = Instance().createApiService(AppConstants.BASE_SERVER_IP);
}
@Override
public void unSubscribe() {
if (mCompositeSubscription != null && !mCompositeSubscription.isUnsubscribed()) {
mCompositeSubscription.clear();
mCompositeSubscription.unsubscribe();
}
}
@Override
public void addSubscribe(Subscription subscription) {
if (mCompositeSubscription == null) {
mCompositeSubscription = new CompositeSubscription();
}
mCompositeSubscription.add(subscription);
}
}
4.BaseMvpActivity基类
通过泛型规定Presenter,并且暴露抽象⽅法createPresenter()给⼦类来创建Presenter,基类实现IView中的公共⽅法,减少⼦类代码的冗余。⾄于BaseMvpActivity功能根据项⽬业务需求进⾏封装。
public abstract class BaseMvpActivity<P extends BasePresenter> extends AppCompatActivity implements IView {    protected P mPresenter;
private Unbinder unbinder;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(getLayoutId());
unbinder = ButterKnife.bind(this);
// 初始化Presenter
initPresenter();
}
private void initPresenter() {
mPresenter = createPresenter();
/
/ 完成Presenter和view的绑定
if (mPresenter != null) {
mPresenter.attachView(this);
}
}
@Override
protected void onDestroy() {
// 将Presenter和view解绑
if (mPresenter != null) {
mPresenter.detachView();
mPresenter = null;
}
// 解绑ButterKnife
if (unbinder != null) {
unbinder.unbind();
mvp
}
}
@Override
public void showLoading() {
// 这⾥实现⾃⼰的加载弹框
}
@Override
public void dismissLoading() {
// 取消弹框
}
@Override
public void onFail(Throwable ex, String code, String msg) {
// 基础的⽹络请求失败处理
}
@Override
public void onNetError() {
// ⽹络错误处理
}
/**
* 页⾯初始化数据
*/
protected void initData() {
}
/**
* 创建Presenter
*
* @return Presenter
*/
protected abstract P createPresenter();
/**
* 获取当前activity的id
*
* @return 当前xml的布局res ID
*/
protected abstract int getLayoutId();
/**
* 初始化view控件
*/
protected abstract void initView();
}
使⽤MVP
1.契约类Contract
通过契约类来管理Model、View、Presenter的所有接⼝,这样使得Presenter和View有哪些功能⼀⽬了然,维护起来也⽅便,同时使得View与Presenter⼀⼀对应,并有效地减少类的数⽬。
public interface LoginContract {
interface View extends IView {
/**
* 登录成功
*/
void onLoginSuccess(UserInfo data);
/**
* 登录失败
*/
void onLoginFail(Throwable ex, String code, String msg);
}
interface Presenter {
void login(String phone, String password);
}
interface Model extends IModel {
/**
* 登录
*
* @param map ⽤户登陆信息
* @param subscriber 回调
*/
void login(Map map, Subscriber subscriber);
}
}
2.LoginPresenter