Android应用MVP实践——MingMVP

前言

    在Android应用开发领域有三种开发模式MVC,MVP和MVVM。三种开发架构各有各的优势。都是为了分离视图层和业务逻辑层解决它们之间的耦合。本文记根据自己对MVP的理解实现Android MVP开发模式的实现——MingMVP。本文针对已对MVP开发模式有所了解的同学。对MVP开发模式还不是很了解的同学可以参考以下文章:
Android MVP 详解(上)
Android MVP 详解(下)

传统的MVP模式

    大多数人在了解MVP开发模式之后也会写出简单的MVP实现。简单的MVP模式如下:

#BaseView
public interface BaseView{
//空
}

#BasePresenter
public interface BasePresenter{
    void start();
    void destroy();
//空
}

#MainContract
public interface MainContract{
    interface View extends BaseView{
        Context getContext();
        //View层要实现的接口
    }
    interface Presenter extends BasePresenter{
        //Presenter层要实现的接口
    }
}

#MainActivity
public class MainActivity implements MainContract.View{
    private MainPresenter mPresenter;

    public void onCreate(Bundle saved..){
        super.onCreate(saved...);
        setContentView(...);
        mPresenter = new MainPresenter(this);
        ...
        mPresenter.start();
        ...
    }

    public void onDestroy(){
        super.onDestroy();
        mPresenter.destory();
    }

    public Context getContext(){
        return 上下文实例。
    }

}

#MainPresenter
public class MainPresenter implements MainContract.Presenter{
    private MainContract.View mView;

    public MainPresenter(MainContract.View view){
        this.mView = view;
    }

    public void start(){
        //业务初始化代码
    }

    public void destroy(){
        //业务结束代码
    }

    .....具体接口实现
}

    上面代码就是简单的一个MVP模式的实现。上面的代码特点是简洁。但是我们发现在我们要执行Presenter层的代码时都需要View层调用一下Presenter的方法,也就是View层驱动Presenter层执行具体业务逻辑。现在能不能每次写MVP模式的界面,View层不需要显式调用Presenter的启动方法。让Presenter层拥有View层一样的生命周期呢?MingMVP就是为了让开发者从每次写MVP模式界面都要让View层调用一下Presenter层的初始化代码解放,让Presenter层拥有View层相同的生命周期,让Presenter当家做主(当然也是假的当家作主,只不过在用MingMVP这框架的开发者开来确实是”当家作主”)。

注:由于Model层的写法每个人、公司都有所不同,为了让MingMVP通用,不考虑Model的写法,当然也不要在View层出现Model层相关的逻辑。

MingMVP

MingMVP的使用

    在讲解MingMVP如何实现之前,大概讲一下MingMVP的使用,让读者们了解Presenter层是如何“当家作主”的。

1.创建UI交互接口
public interface MainContract {
    interface View extends IView{
        void operationView1();
        void operationView2();
    }

    interface Presenter extends IPresenter{
        void operation1();
    }
}
2.创建Presenter层类,继承BasePresenter并实现具体Presenter接口
public class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter {
    public MainPresenter(Context ctx, MainContract.View v) {
        super(ctx, v);
    }

    @Override
    public void operation1() {
        ...
        mView.operationView1();
        ...
    }


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        ...相当于Activity的onCreate生命期
    }

    //还有onResume、onStart等等Activity相似的生命周期,除了onCreate方法,其他生命周期  的实现不是必须的。
}
3.创建View层继承BaseMVPActivity/BaseMVPFragment/BaseMVPDialog并实现View接口
public class MainActivity extends BaseMVPActivity<MainContract.Presenter> implements MainContract.View {

    Button btn_load;
    TextView tv_data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    protected MainContract.Presenter createPresenter() {
        return new MainPresenter(this, this);
    }

    @Override
    protected void bindViews() {
        btn_load = findView(R.id.btn_main_load);
        tv_data = findView(R.id.tv_main_data);
        btn_load.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.operation1();
            }
        });

    }

    @Override
    public int getLayoutID() {
        return R.layout.activity_main;
    }

    @Override
    public void operationView1() {
        tv_data.setText("点击按钮");
    }

    @Override
    public void operationView2() {
        tv_data.setText("Presenter onCreate");
    }
}

    在上面可以看到,在Presenter层也有Activity一样的onCreate,View层除了createPresenter中创造了Presenter后,View层和Presenter层的地位平等了。Presenter有了和Activity一样的生命周期,能决定自己在什么时候干什么事。在生命周期内View层和Presenter层都能平等的调用相互之间开放的接口,而无须View层驱动。当然交互操作还是需要View层通知Presenter层执行相应的业务逻辑代码。

MingMVP的实现原理

    MingMVP的实现只有7个文件。
MingMVP
以下是对每个java文件的说明:
IView:作为View层的一个标识接口。
IPresenter:作为Presenter层的一个标识接口。
IMVPView:View层都需要实现的接口。
BasePresenter:Presenter层的基类,只包含Presenter生命周期方法和View层的引用。
BaseMVPActivity/Dialog/Fragment:View层的基类。
    由于IView和IPresenter只作为标识接口,这里就不贴出其代码。

IMVPView

public interface IMVPView {
    /**
     * Specify layout id for the view content.
     */
    @LayoutRes int getLayoutID();


}

    这个接口需要View层实现,这里只有一个方法getLayoutID,主要用于返回View层的layout文件。

BasePresenter

/**
 * Base class of Presenter.
 * Created by luozm on 2017/7/19.
 */

public abstract class BasePresenter<T extends IView> {
    private Context mContext;
    private T mView;

    public BasePresenter(Context ctx, T v) {
        this.mContext = ctx;
        this.mView = v;
    }

    public abstract void onCreate(@Nullable Bundle savedInstanceState);

    //销毁View层引用以免循环引用导致View层类的内存泄漏,当然也可以用弱引用解决
    public void onDestroy() {
        mContext = null;
        mView = null;
    }

    public void onStart() {
    }

    public void onStop() {
    }

    public void onResume() {
    }

    public void onPause() {
    }

    public void onRestart(){}

    public void onSave(Bundle savedInstance) {
    }

    public void onRestore(Bundle savedInstance) {
    }

    public T getView(){
        return mView;
    }

    public Context getContext(){
        return mContext;
    }
}

    BasePresenter代码很简单,主要是生命周期的空实现和接收View层实例的构造方法。

BaseMVPActivity

public abstract class BaseMVPActivity<T extends IPresenter> extends AppCompatActivity implements IMVPView {

    protected T mPresenter;
    private WeakReference<BasePresenter> delegate;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutID());
        mPresenter = createPresenter();
        //mPresenter和delegate指向同一个实例,对开发者进行规范,若P层实现类不是BasePresenter的子类则报错
        if (mPresenter instanceof BasePresenter) {
            delegate = new WeakReference<BasePresenter>((BasePresenter) mPresenter);
        } else {
            throw new IllegalArgumentException("Presenter must extends BasePresenter");
        }
        bindViews();
        preCreate(savedInstanceState);
        delegate.get().onCreate(savedInstanceState);
        postCreate(savedInstanceState);
    }

    /**
     * Create Presenter for this Activity.
     */
    protected abstract T createPresenter();

    protected T getPresenter(){
        return mPresenter;
    }

    /**
     * You can do something after Presenter Created in this method.
     * 在Presenter的onCreate方法调用之后执行
     */
    protected void postCreate(Bundle savedInstanceState) {
    }

    /**
     * You can do something before Presenter Created in this method.
     * 在Presenter的onCreate方法调用之前执行
     */
    protected void preCreate(Bundle savedInstanceState) {
    }

    /**
     * Bind view for this activity.
     */
    protected abstract void bindViews();

    /**
     * Simple way to findView without cast the type.
     */
    public <T extends View> T findView(int id) {
        return (T) findViewById(id);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        delegate.get().onDestroy();
        mPresenter = null;
    }

    @Override
    protected void onStart() {
        super.onStart();
        delegate.get().onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        delegate.get().onStop();
    }

    @Override
    protected void onResume() {
        super.onResume();
        delegate.get().onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        delegate.get().onPause();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        delegate.get().onRestart();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        delegate.get().onSave(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        delegate.get().onRestore(savedInstanceState);
    }
}

    之前说过,MingMVP的Presenter的”当家作主”并不是真的当家作主,实际还是需要View层驱动其生命周期,对于使用MingMVP框架的同学确实是当家作主。只不过BaseActivity等View层基类帮我们简化大部分MVP实现步骤。这样我们就能简洁而又优雅的实现MVP开发模式。同时在BasePresenter和BaseActivity通过泛型规定了双方互相开放的VP接口,这样使用MingMVP的开发者在V层实现中只能调用XXXContract中的Presenter接口而不能调用Presenter的生命周期方法,P层也只能调用XXXContract中的View接口,真正实现VP分离。

总结

    MingMVP能帮助开发者简化MVP模式开发工作。框架已上传jcenter,在AndroidStudio可直接引用。附上MingMVP的github地址,喜欢的记得点star哦。
Github MingMVP

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sdfsdfdfa/article/details/81591798
文章标签: 开发模式 Android MVP
个人分类: Android
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭