前言
在开发过程中MVC模式的架构是最为常见的,Android本身Activity和XML布局的结合就是比较典型的例子,使用过程中业务的逻辑、数据的处理、View的更新都会在Activity中进行这样代码的复杂度和维护成本就会增高View和Model的耦合度很高,开发者们对于这种情况都会选择进行MVC的封装拆分增加了开发的难度。
MVP是从MVC演化而来全称 Model-View-Presenter,即模型-视图-层现器。而现在Android开发架构中MVP架构已成主流,MVP模式会解除View与Model的耦合,定义了Presenter交互中间人作为View和Model之间的桥梁,它从Model中获取到数据返回给View层使View和Model之间没有耦合,并且将业务逻辑从View中抽离出来。View拥有Presenter成员变量实现逻辑接口,View将操作传递给Presenter,最后由Presenter再将结果返回View。Model就是数据仓库用于数据的存储和获取,Presenter拥有对Model进行数据的存储和获取方法。
此处贴出MVC和MVP思维导图能够清楚的看出两种模式之前的区别
使用
马上开始我们的实战MVP架构搭建
1.定义基础的IModel、IView、IPresenter接口,用于定义提供公共方法的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
public interface IModel {
void onDestroy(); }
import androidx.annotation.NonNull; public interface IView {
default void showLoading() {
}
default void hideLoading() {
}
void showMessage(@NonNull String message); }
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.OnLifecycleEvent;
import org.jetbrains.annotations.NotNull; public interface IPresenter extends LifecycleObserver {
void onStart();
void onDestroy();
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE) void onCreate(@NotNull LifecycleOwner owner);
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) void onDestroy(@NotNull LifecycleOwner owner);
}
|
2.定义抽象的Persenter业务处理类BasePresenter,关联抽象层IView和抽象IModel并实现基础的IPresenter接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| import android.app.Service; import android.view.View;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.OnLifecycleEvent;
import com.mi.qing.common.net.frame.util.RxLifecycleUtils; import com.uber.autodispose.AutoDisposeConverter;
import org.jetbrains.annotations.NotNull;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable;
public abstract class BasePresenter<M extends IModel, V extends IView> implements IPresenter { protected CompositeDisposable mCompositeDisposable; protected M mModel; protected V mRootView; private LifecycleOwner lifecycleOwner;
public BasePresenter(M model, V rootView) { this.mModel = model; this.mRootView = rootView; onStart(); }
protected <T> AutoDisposeConverter<T> bindLifecycle() { if (null == lifecycleOwner) { throw new NullPointerException("lifecycleOwner == null"); } return RxLifecycleUtils.bindLifecycle(lifecycleOwner); }
@Override public void onStart() {
}
@Override public void onDestroy() { unDispose(); if (mModel != null) { mModel.onDestroy(); } this.mModel = null; this.mRootView = null; this.mCompositeDisposable = null; }
@Override public void onCreate(@NotNull LifecycleOwner owner) { Log.e("BasePresenter", "onCreate: LifecycleOwner " ); this.lifecycleOwner = owner;
}
@Override public void onDestroy(@NotNull LifecycleOwner owner) { Log.e("BasePresenter", "onDestroy: LifecycleOwner " ); owner.getLifecycle().removeObserver(this); }
public void addDispose(Disposable disposable) { if (mCompositeDisposable == null) { mCompositeDisposable = new CompositeDisposable(); } mCompositeDisposable.add(disposable); }
public void unDispose() { if (mCompositeDisposable != null) { mCompositeDisposable.clear(); } } }
|
3.定义抽象的BaseMvpActivity基类,通过泛型规定Presenter,并且暴露抽象方法createPresenter()给子类来创建Presenter,基类实现IView中的公共方法,减少子类代码的冗余。至于BaseMvpActivity功能根据项目业务需求进行封装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import android.os.Bundle;
import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity;
import com.mi.qing.common.net.frame.base.mvp.IPresenter; import com.mi.qing.common.net.frame.base.mvp.IView;
public abstract class BaseMvpActivity<P extends IPresenter> extends AppCompatActivity implements IView {
protected P mPresenter;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getLayoutId()); initPresenter(); }
private void initPresenter() { mPresenter = createPresenter(); if (mPresenter != null) { getLifecycle().addObserver(mPresenter); mPresenter.onStart(); } }
@Override protected void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.onDestroy(); mPresenter = null; } }
@Override public void showLoading() { }
@Override public void hideLoading() { }
@Override public void showMessage(String message) { }
protected abstract P createPresenter();
protected abstract int getLayoutId();
}
|
4. 使用MVP架构,添加契约接口Contract,通过契约接口来管理Model、View、Presenter的所有接口,维护起来也方便,同时Model、View、Presenter关联一一对应一目了然,
并有效地减少类的数目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import com.mi.qing.common.net.frame.base.mvp.IModel; import com.mi.qing.common.net.frame.base.mvp.IView; import com.mi.qing.common.net.frame.bean.BaseApiResult;
import io.reactivex.Observable;
public interface TestContract {
interface View extends IView {
void onLoginSuccess(String message);
}
interface Presenter {
void login(); }
interface Model extends IModel { Observable<BaseApiResult<String>> getTop(); }
}
|
5. 创建测试TestPresenter类处理登录的逻辑,继承BasePresenter关联契约接口中定义的Model和View接口并实现定义的Presenter接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class TestPresenter extends BasePresenter<TestContract.Model,TestContract.View> implements TestContract.Presenter{
public TestPresenter(TestContract.Model model, TestContract.View rootView) { super(model, rootView); }
@Override public void login() { mRootView.showLoading(); mModel.getTop() .as(bindLifecycle()) .subscribe(data->{ mRootView.onLoginSuccess("登录成功啦"); mRootView.hideLoading(); },throwable -> { throwable.printStackTrace(); }); } }
|
6. 创建测试TestModel类处理登录的数据获取,实现契约接口定义的Model接口,用于TestPresenter类调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import com.mi.qing.common.net.frame.bean.BaseApiResult; import com.mi.qing.common.net.source.impl.TestServiceImpl;
import io.reactivex.Observable;
public class TestModel implements TestContract.Model{
@Override public void onDestroy() {
}
@Override public Observable<BaseApiResult<String>> getTop() { return TestServiceImpl.getInstance().getTop(); } }
|
7. 添加测试的View类MvpTestActivity,继承BaseMvpActivity泛型定义TestPresenter类,并实现契约接口中定义的View接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import android.annotation.SuppressLint; import android.view.View; import android.widget.Toast;
import com.mi.qing.common.net.frame.base.BaseMvpActivity; import com.mi.qing.common.net.mvp.TestContract; import com.mi.qing.common.net.mvp.TestModel; import com.mi.qing.common.net.mvp.TestPresenter;
public class MvpTestActivity extends BaseMvpActivity<TestPresenter> implements TestContract.View {
@Override protected TestPresenter createPresenter() { TestModel testModel = new TestModel(); return new TestPresenter(testModel, this); }
@Override protected int getLayoutId() { return R.layout.activity_mvp_test; }
@SuppressLint("ShowToast") @Override public void onLoginSuccess(String message) { Toast.makeText(MvpTestActivity.this, message, Toast.LENGTH_SHORT).show(); }
public void clickLogin(View view) { mPresenter.login(); } }
|
使用效果截图
总结
基础的MVP架构搭建完毕,读者可按需调整内部逻辑及处理。没有恒古不变的架构,只有在变化中找出适合自己项目的架构。后续章节还会介绍MVVM架构的有点及搭建方式,技术在于实践马上开始搭建属于自己的MVP架构吧。
框架及Demo源码
源码地址 MiQingWang/CommonNetFrame