Model-View-Presenter 设计模式

  你可能听过MVC设计模式,甚至你在各种框架(例:.Net)下都使用了该模式。然而当我尝试用一种新的设计模式去实现我的Android程序的时候,我发现了MVP模式。MVP和MVC最本质的区别是,MVP在present实现UI上的业务逻辑然后通过接口和外部通讯。

  下面我将通过例子来展现如何在Android程序里通过MVP模式来提高代码的可测试性(这里主要是单元测试)。我们的例子是这样的,在App要启动的时候,我们需要有个欢迎界面,这个欢迎界面后台运行着初始化数据的方法,在进入app主界面前,我们需要在欢迎界面提供一个进度条以此来检测是否网络环境正常,如果网络环境不ok,那我们显示一个错误页面。如果网络环境ok那就直接进入app主界面。

  建启动页的同时,我们同时创建一个presenter来负责model和view的通信。在本例中presenter应该具备两个功能:判断是否网络正常和view的处理,以下是我的工程的结构:

presenter模块会引用model模块,这里的model模块是ConnectStatus,他实现了IConnectStatus接口。

1 package com.sample.mvp.model;
2 
3 /**
4  * Created by wuruize on 2015/1/27.
5  */
6 public interface IConnectStatus {
7 
8     public abstract boolean isOnline();
9 }

和你想象的一样,管理view模块的是实现了ISpalshView接口的Activity。实现了这个接口类将会被presenter控制,如下:

package com.sample.mvp.view;

/**
 * Created by wuruize on 2015/1/27.
 */
public interface ISpalshView {

    public abstract void hideProgress();

    public abstract void showProgress();

    public abstract void showNoInetErroMsg();

    public abstract void moveToMain();
}

在编写Android程序的时候,view模块会首先被创建,然后会被交给presenter:

package com.sample.mvp.view.impl;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

import com.sample.mvp.R;
import com.sample.mvp.presenter.SpalshPresenter;
import com.sample.mvp.view.ISpalshView;


public class SpalshActivity extends ActionBarActivity implements ISpalshView {

    private SpalshPresenter mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPresenter = new SpalshPresenter(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mPresenter.didFinishLoading();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void hideProgress() {

    }

    @Override
    public void showProgress() {

    }

    @Override
    public void showNoInetErroMsg() {

    }

    @Override
    public void moveToMain() {

    }
}

首先我们初始化Activity,然后我们把Activity实例给presenter构造presenter实例,重写  onResume()  让presenter模块接管view模块,present代码如下:

package com.sample.mvp.presenter;

import com.sample.mvp.model.impl.ConnectStatus;
import com.sample.mvp.view.ISpalshView;

/**
 * Created by wuruize on 2015/1/27.
 */
public class SpalshPresenter {

    private ISpalshView mSpalshView;
    private ConnectStatus mStatus;

    public SpalshPresenter(ISpalshView view) {
        this.mSpalshView = view;
        mStatus = new ConnectStatus();
    }

    public void didFinishLoading() {
        if(mStatus.isOnline()) {

        } else {
            mSpalshView.hideProgress();
            mSpalshView.showNoInetErroMsg();
        }
    }
}

presenter模块会持有实现了ISpalshView接口的引用,实现IConnectStatus的model用于判断网络是否ok。基于此,我们可以通过view模块做不同的事情,和我们看到的一样,我们不需要知道view的具体实现(是被Activity实现还是其他)。如此,降低解耦。能够轻易作修改,进行单元测试。

  在单元测试的时候,你是不是有那样一个痛点,由于Activity功能元素功能都较为复杂,想要测试某个具体功能块的话,很浪费时间,降低了开发效率。而如果你使用了MVP模式,不需要依赖于View的具体实现,做到真正的test-driven development.

  声明:文章里面的东西基本来自于《50 Android Hacks》理解和翻译,特此感谢此书。

原文地址:https://www.cnblogs.com/wuruize/p/4255994.html