Android MVP设计模式

一,前言:

关于Android程序的构架, 当前最流行的模式即为MVP模式, Google官方便提供了Sample代码来展示这种模式的用法.Repo地址: android-architecture.
之所以人们会提到MVP这种设计模式,是因为它与传统的MVC模式相比,使得view层与model层完全解耦,作为view层的activity或者fragment不再臃肿,特别是交互逻辑比较复杂的情况下尤为明显。

二,MVC与MVP对比:

对于MVC与MVP的比较,网上有许多资料,我这里就不详细阐述了,下面就通过两种模式的对比图来简单的总结一下吧。

MVC模式图
MVP模式图
总结:

MVC中的视图和数据是互相耦合在一起的,只要对其中一部分加以改动,其他和之相关的数据和视图都要受到牵连;而MVP中的数据和视图则是通过中间的presenter来连接的。View不直接与Model交互 ,而是通过与Presenter交互来与Model间接交互。通常Presenter与View的交互是通过接口来进行的,更有利于添加单元测试。

三,简单案例

一开始接触MVP设计模式时,也是有点分不清头脑,主要是其中相关的类变多了,各种接口和实现类,有点让人抓狂。后面通过参考了网上几遍相关的案例文章,自己总结了一下,按照一定的思路来写,还是清楚很多。下面我就把自己总结的方法一步步通过案例来实现下,有不足之处,还望大家指正。

文中例子是个简单的请求网络,获取天气的情景。废话不多说,先看实现步骤。

步骤一:先根据业务要求,思考界面主要有哪些实现及展示效果,从而设计view层的接口

/**
 * 定义界面的一些行为状态
 * Created by Administrator on 2018/4/2.
 */

public interface IgetWeatherView {
    void showLoading();
    void hideLoading();
    void getWeatherFialed();//获取天气失败
    void getWeatherSuccess(WeatherBean.WeatherInfo weatherInfo);//获取天气成功
    void displayWeatherInfo(WeatherBean.WeatherInfo weatherInfo);//展示天气结果
}

步骤二:根据需要的获取的数据,定义数据层的基本接口

public interface IWeahter {
    void getWeatherInfo(Context mContext,String url, WeatherListener weatherListener);
   /**
     * 获取天气结果接口回调
     */
    interface WeatherListener{
        void getSuccess(WeatherBean.WeatherInfo weatherBean);
        void getFailed();
    }
}

步骤三:设置数据获取的实现类(真实获取数据的地方)

public class WeatherImpl implements IWeahter{

    @Override
    public void getWeatherInfo(Context mContext, String url, final WeatherListener weatherListener) {
        VolleyRequestUtil.requestGet(mContext, url, "weather", WeatherBean.class, new VolleyListenerInterface(mContext,
                VolleyListenerInterface.mListener,VolleyListenerInterface.mErrorListener) {
            @Override
            public void onSuccess(Object result) {
                WeatherBean weatherBean = (WeatherBean) result;
                weatherListener.getSuccess(weatherBean.weatherinfo);
            }

            @Override
            public void onError(VolleyError error) {
                weatherListener.getFailed();
            }
        });
    }

}

步骤四:设计提供逻辑交互的presenter层,该层必须持有view和model层的引用,然后在逻辑交互过程中把两者进行关联。

public class WeatherPresenter {

    private IWeahter iweather;
    private IgetWeatherView getWeatherView;

    public WeatherPresenter (IgetWeatherView  getWeatherView){
        this.getWeatherView= getWeatherView;
        iweather= new WeatherImpl();
    }

    /**
     * 获取天气信息
     * @param context
     */
    public void getWeatherInfo(Context context){
        getWeatherView.showLoading();
        iweather.getWeatherInfo(context, "http://www.weather.com.cn/data/sk/101010100.html", new IgetWeatherView .WeatherListener() {
            @Override
            public void getSuccess(WeatherBean.WeatherInfo weatherInfo) {
                getWeatherView.hideLoading();
                getWeatherView.getWeatherSuccess(weatherInfo);
                getWeatherView.displayWeatherInfo(weatherInfo);
            }

            @Override
            public void getFailed() {
                getWeatherView.hideLoading();
                getWeatherView.getWeatherFialed();
            }
        });
    }

步骤五,view层的实现(Activity)。有了presenter,activity的具体实现只要实现view层的基本接口即可,剩下的只是利用presenter做简单的界面实现

public class MainActivity extends FragmentActivity implements IgetWeatherView{

    private Button request_btn;
    private TextView display_weather_tv;
    private WeatherPresenter weahterPresenter;
    private ProgressBar progressbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initListener();
    }

    private void initView() {
        display_weather_tv = (TextView) findViewById(R.id.display_weather_tv);
        request_btn= (Button) findViewById(R.id.request_btn);
        progressbar= (ProgressBar)findViewById(R.id.progressbar);
        weahterPresenter= new WeatherPresenter(this);
    }

    private void initListener() {
        request_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                weahterPresenter.getWeatherInfo(MainActivity.this);

            }
        });
    }

    @Override
    public void showLoading() {
        progressbar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        progressbar.setVisibility(View.GONE);
    }

    @Override
    public void getWeatherFialed() {
        Toast.makeText(this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void getWeatherSuccess(WeatherBean.WeatherInfo weatherInfo) {
        Log.d("TAG", "city is " + weatherInfo.getCity());
        Log.d("TAG", "temp is " + weatherInfo.getTemp());
        Log.d("TAG", "time is " + weatherInfo.getTime());
    }

    @Override
    public void displayWeatherInfo( WeatherBean.WeatherInfo weatherInfo) {
        display_weather_tv.setText("city is "+weatherInfo.getCity() +
                "temp is "+weatherInfo.getTemp() +
                "time is "+weatherInfo.getTime());
    }

最后的话:

上述例子中只贴了核心代码,其中网络是自己分装的volley请求,这部分内容以后有时间再总结一下。使用MVP模式后发现,代码量和类确实变多了,不过回过头来,看activity的代码,确实简洁了很多。可能这个例子还不是很明显,不过对于项目比较大,界面逻辑比较多的情况下,使用MVP的模式的确能放大其优势。不过,最终,在自己的项目中该使用什么模式,还是取决于具体项目大小以及复杂程度,还有团队的协作情况。总之,没有最好的模式,只有最适合团队的模式。不过,作为一名android开发者,每一种设计模式都应该了解,这样在将来要用到的时候才能随心所欲的使用,不至于犯怵。好了,关于MVP设计模式就写到这里,大家有什么疑问的,欢迎一起交流学习。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容