zoukankan      html  css  js  c++  java
  • 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》理解和翻译,特此感谢此书。

  • 相关阅读:
    C语言使用指针表示数组的注意事项
    LUNA16数据集的百度云链接
    c语言定义指针类型需注意事项
    对DeepLung数据预处理部分的详细展示
    python统计字符串中字符个数
    C语言预处理命令之文件包含
    C语言值拷贝传递机制
    【论文】CornerNet:几点疑问
    解读 pytorch对resnet的官方实现
    python 对三维CT数据缩放
  • 原文地址:https://www.cnblogs.com/wuruize/p/4255994.html
Copyright © 2011-2022 走看看