框架模式MVC与MVP在Android中的应用

很多人在开发Android项目时没有考虑过架构模式的问题,以至于随着项目的增大,Activty或者Fragment中代码也会越来越多,导致项目的维护变的越来越复杂。然而在Android中使用比较多的两种框架模式就是MVC和MVP,下面我将分别介绍一下这两种框架模式。

一、MVC框架模式

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。其中M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。

其实MVC在J2EE开发中应用是很多的,它将业务逻辑与界面分离开来,通过控制器将其连接,从而达到了很好的解耦效果,通过MVC编写的代码有利于后期的维护和改造。

在Android开发中,我们也是经常看到MVC框架模式的身影,例如我们开发Android端应用时,界面编写时在XML中,而我们经常回把网络访问数据独立出来,再通过Activity处理用户交互的问题,这就是一种MVC的思想。采用MVC模式的好处是便于UI界面部分的显示和业务逻辑,数据处理分开。下面具体以MVC的表现形式描述一下:

M层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理。

V层:应用层中处理数据显示的部分,XML布局可以视为V层,显示Model层的数据结果。

C层:在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据(eg.读取当前EditText控件的数据),控制用户输入(eg.EditText控件数据的输入),并向Model发送数据请求(eg.发起网络请求等)。

为方便理解,我下面举一个例子,由于MVC容易理解,也鉴于篇幅问题,这里只给出简短的伪代码,因为具体的代码也没有什么意义:

我们通过一个获取天气预报数据的小项目来解读 MVC for Android

      Controller控制器

public class MainActivity extends Activity implements StrUIDataListener {
    private StrVolleyInterface networkHelper;
    private StrVolleyInterface expertNetworkHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        }
    //加载网络数据
    private void initDate() {
        try {
            networkHelper = new StrVolleyInterface(DemandDetailActivity.this);
            networkHelper.setStrUIDataListener(DemandDetailActivity.this);
            ApiClient.getDataDetail(DemandDetailActivity.this, id, networkHelper);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onDataChanged(String data) {
        //数据加载成功
        //....更新UI
    }
    @Override
    public void onErrorHappened(VolleyError error) {
        Toast.makeText(DemandDetailActivity.this, "加载错误,请检查网络!", Toast.LENGTH_SHORT).show();
    }
}

从上面代码可以看到,Activity持有了ApiClient网络请求模型的对象,当我们需要获取数据时,只需要调用initData()方法。比如我们点击Button,Activity作为Controller控制层会处理View视图层,并调用ApiClient.getDataDetail方法,当Model模型处理数据结束后,通过接口onDataChanged通知View视图层数据处理完毕,View视图层该更新界面UI了。然后View视图层去更新界面。看到这里,我们会发现整个MVC框架流程就在Activity中体现出来了。

 Model模型

这里ApiClient就是充当Model层的,专门用于处理网络数据请求,代码就不展示了,读者只要理解就行。

上面的例子中,Activity将View视图显示和Model模型数据处理隔离开了。activity担当contronller完成了model和view之间的协调作用。

那么我们为什么要这样实现,直接在Activity中实现网球请求不是更方便吗?

很多人可能会有这种疑问,可是大家想想,如果这种网络请求都在Activity中实现的话,一是不利于代码复用,而是后期维护起来是很困难的。比如我们现在的网络请求用的是Volley,以后想换成NoHttp实现的话,我们好需要修改每一个Activity类,这是不是很繁琐,看到这里我们就会发现MVC的好处了。

MVC简要总结:

Android项目中,业务逻辑,数据处理等担任了Model(模型)角色,XML界面显示等担任了View(视图)角色,Activity担任了Contronller(控制器)角色。contronller(控制器)是一个中间桥梁的作用,通过接口通信来协同 View(视图)和Model(模型)工作,起到了两者之间的通信作用。

我们发现,其实控制器Activity主要是起到解耦作用,将View视图和Model模型分离,虽然Activity起到交互作用,但是Activity中有很多关于视图UI的显示代码,因此View视图和Activity控制器并不是完全分离的,也就是说一部分View视图和Contronller控制器Activity是绑定在一个类中的。所以MVC应用在Android中,它的解耦效果并不是十分的完美,当我们的APP逐渐变大时,我们还会发现我们的Activity和Fragment会越来越庞大。

因此如果我们开发的Android项目不是很庞大,用MVC框架模式还是比较理想的,如果我们的项目是比较庞大,而且后期经常需要修改维护的话,我更建议使用MVP框架模式,下面对MVP框架模式做一个简单的介绍。

二、MVP框架模式

什么是MVP

MPV 是从经典的MVC模式演变过来的,其基本思路都是相通的。

MVP是模型(Model)、视图(View)、控制者(Presenter)的缩写,分别代表项目中3个不同的模块。

        模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;

        视图(View):负责界面数据的展示,与用户进行交互;

        控制者(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

在Andorid项目中,我们习惯将Activity作为MVC中的控制者来达到Model模型和View视图分离,但是在MVP框架模式中,通常将Activity作为View视图层,因为在MVC框架模式中Activity和View视图显示关联紧密,Activity中包含大量的View视图显示代码,如果哪天老板说需要修改View视图显示,这时候你是不是感觉需要修改Activity中的大量代码?这么一来会将Activity中控制逻辑破坏,也导致Activity中承担太多的职责。根据单一职责原则,Activity主要起到用户交互作用,也就是接收用户输入,显示请求结果。因此可以通过MVP框架模式来减轻Activity的职责。

如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。这就是MVP模式的整个核心过程。

这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。

我举一个获取天气的例子来说明,这样大家会很容易看懂

      Model模型

/**
 * 天气Model接口
 */
public interface WeatherModel {
    void loadWeather(String cityNO, OnWeatherListener listener);
}
.........
/**
 * 天气Model实现
 */
public class WeatherModelImpl implements WeatherModel {
    @Override
    public void loadWeather(String cityNO, final OnWeatherListener listener) {
        /*数据层操作*/
        VolleyRequest.newInstance().newGsonRequest("http://www.weather.com.cn/data/sk/" + cityNO + ".html",
                Weather.class, new Response.Listener<weather>() {
                    @Override
                    public void onResponse(Weather weather) {
                        if (weather != null) {
                            listener.onSuccess(weather);
                        } else {
                            listener.onError();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        listener.onError();
                    }
                });
    }
}

和MVC一样,Model的代码不变,只是用与处理网络请求,请求成功后接口回调将Model模型处理的数据返回给Presenter控制者。

      Presenter控制器

/**
 * 天气 Presenter接口
 */
public interface WeatherPresenter {
    /**
     * 获取天气的逻辑
     */
    void getWeather(String cityNO);

}
..........

/**
 * 在Presenter层实现,给Model层回调,更改View层的状态,确保Model层不直接操作View层
 */
public interface OnWeatherListener {
    /**
     * 成功时回调
     *
     * @param weather
     */
    void onSuccess(Weather weather);
    /**
     * 失败时回调,简单处理,没做什么
     */
    void onError();

}
.........

/**
 * 天气 Presenter实现
 */
public class WeatherPresenterImpl implements WeatherPresenter, OnWeatherListener {
    /*Presenter作为中间层,持有View和Model的引用*/
    private WeatherView weatherView;
    private WeatherModel weatherModel;

    public WeatherPresenterImpl(WeatherView weatherView) {
        this.weatherView = weatherView;
        weatherModel = new WeatherModelImpl();
    }

    @Override
    public void getWeather(String cityNO) {
        weatherView.showLoading();
        weatherModel.loadWeather(cityNO, this);
    }

    @Override
    public void onSuccess(Weather weather) {
        weatherView.hideLoading();
        weatherView.setWeatherInfo(weather);
    }

    @Override
    public void onError() {
        weatherView.hideLoading();
        weatherView.showError();
    }
}

从代码中我们可以看到Presenter控制器同时持有 WeatherModel和WeatherView对象且实现了OnWeatherListener接口取回Model模型数据,因此,WeatherPresenterImpl向WeatherModel发送数据请求,然后通过OnWeatherListener接口实现获取请求结果,在将结果通过接口WeatherView把数据显示到Activity担当的View视图中。从而达到彻底将Model和View完全分离,试想在这种情况下,如果你需要修改Model是完全不会影响View视图代码的修改的,同理,修改View视图层的时候,也完全无需修改Model层。相当于Model和View互相不知道对方的存在,都是通过中间控制器Presenter来传达通信。

      View视图

先定义一个View视图显示的接口WeatherView

新闻列表模块主要是展示从网络获取的新闻列表信息,View层的接口大概需要如下方法:

  (1)加载数据的过程中需要提示“正在加载”的反馈信息给用户

  (2)加载成功后,将加载得到的数据填充到RecyclerView展示给用户

  (3)加载成功后,需要将“正在加载”反馈信息取消掉

  (4)若加载数据失败,如无网络连接,则需要给用户提示信息

  根据上面描述,我们将View层的接口定义如下,分别对应上面四个方法:

public interface WeatherView {
    void showLoading();

    void hideLoading();

    void showError();

    void setWeatherInfo(Weather weather);
}

然后实现Activity实现WeatherView接口

/**
 * 天气界面
 */
public class WeatherActivity extends BaseActivity implements WeatherView, View.OnClickListener {
    ..........................
    private WeatherPresenter weatherPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();

    }

    private void init() {
 <span style="white-space:pre">	</span>....................

        findView(R.id.btn_go).setOnClickListener(this);

        weatherPresenter = new WeatherPresenterImpl(this); //传入WeatherView
        loadingDialog = new ProgressDialog(this);
        loadingDialog.setTitle("加载天气中...");
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_go:
                weatherPresenter.getWeather(cityNOInput.getText().toString().trim());
                break;
        }
    }

    @Override
    public void showLoading() {
        loadingDialog.show();
    }

    @Override
    public void hideLoading() {
        loadingDialog.dismiss();
    }

    @Override
    public void showError() {
        //Do something
        Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setWeatherInfo(Weather weather) {
        WeatherInfo info = weather.getWeatherinfo();
        //更新界面
        .....................
    }

}

总结:

MVP框架模式完全将Model模型和View视图分离,从而使得代码的耦合低,利用MVP框架写项目达到解耦作用。 MVP和MVC最大的区别是:MVC中的V和C关系比较紧密,耦合度太高,从C中访问M获取数据一定程度上也可以看成从V中访问M。而MVP中M和V完全分离,互相不知道对方的存在,Presenter通过接口通信方式将V和M通信。 在Android中MVP框架 Activity担当View视图层,MVC框架模式Activity担当控制器。

虽然MVP可以达到很好的解耦效果,可是在开发的过程中需要多写一层(Presenter)的代码,代码量会扩大,而且业务逻辑对不太熟悉的开发者来说还是略显复杂,因此建议如果开发相对较小的项目,而且项目不需要频繁的修改可以选用MVC,如果开发比较大的项目,而且需要后期不断地维护修改的话建议使用MVP框架模式开发。

时间: 2024-11-29 05:26:57

框架模式MVC与MVP在Android中的应用的相关文章

框架模式 MVC 在Android中的使用

算来学习Android开发已有2年的历史了,在这2年的学习当中,基本掌握了Android的基础知识.越到后面的学习越感觉困难,一来是自认为android没啥可学的了(自认为的,其实还有很多知识科学),二来网络上的很多框架已经帮我们做了太多的事情了,我们只需要画画UI就可以了,感觉Android开发没有太多的技术含金量.最近闲来无事,开始总结之前学过的知识点,想着是否应该学点其他的东西呢?总不能局限于Android基础知识吧.慢慢的探索发现在大的项目工程中,一个好的框架,好的设计模式,能减少很大的

[转]框架模式 MVC 在Android中的使用

算来学习Android开发已有2年的历史了,在这2年的学习当中,基本掌握了Android的基础知识.越到后面的学习越感觉困难,一来是自认为android没啥可学的了(自认为的,其实还有很多知识科学),二来网络上的很多框架已经帮我们做了太多的事情了,我们只需要画画UI就可以了,感觉Android开发没有太多的技术含金量.最近闲来无事,开始总结之前学过的知识点,想着是否应该学点其他的东西呢?总不能局限于Android基础知识吧.慢慢的探索发现在大的项目工程中,一个好的框架,好的设计模式,能减少很大的

框架模式MVP在Android中的使用

前一篇文章中学习了MVC框架模式在Android中的使用,不了解什么是MVC框架模式的亲戳这里 框架模式 MVC 在Android中的使用.其实谷歌Android开发团队是鼓励开发者利用MVC框架模式开发项目的,我们平时写代码也或多或少的在使用MVC框架模式开发项目,比如说谷歌自己退出来的Volley网络请求框架就是遵循MVC框架的.我们可以理解为Volley框架是MVC当中的模型,也就是网络数据处理这一块,无需跟View视图有任何关联.也符合视图和模型分离.可能你会觉得MVC框架已经很好用了,

简述MVC框架模式以及在你(Android)项目中得应用

标题是阿里电话面试的问题,一直以为自己很清楚MVC模式,结果被问到时,这M.V.C这几者之间的关系都搞不清楚了,最主要是,没法将MVC和Android中各个组件对应起来,所以,面试肯定挂了,不过面试也是学习的一种方式,可以知道大公司看中什么,以及自己还有哪些知识漏洞,例如这次面试就学到了很多东西. 大家也可以在看下面的内容之前,也想想能否把MVC及与Android各个组件的对应关系讲清楚,看是否还有和我一样对MVC一知半解的.  如果写的有问题的地方,欢迎讨论.转载请注明出处:http://ww

浅谈应用工厂模式和单例在Android中实现业务隔离

Android中写应用,一样需要考虑到降低耦合性的问题,还有一些其他问题,比如App的增量式更新,业务变更的便捷实现等等,都会有工厂模式和单例的身影. 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式.因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改

MVC、MVP、MVVM 模式(待续)

本文将从收集来的资料整理分析MVC模型的各种应用以及其演化历程 一. 介绍 MV* 模式 MVC.MVP.MVVM 模式都是为了解决图形界面应用程序复杂性管理问题而产生的应用架构模式.追根溯源,从最经典的Smalltalk-80 MVC模式开始逐步还原图形界面之下最真实的MV*模式. GUI程序所面临的问题 图形界面的应用程序提供给用户可视化的操作界面,这个界面提供给数据和信息.用户输入行为(键盘,鼠标等)会执行一些业务逻辑,可能会导致对应用程序数据的变更,数据的变更自然需要用户界面的同步变更以

介绍Model-View-Presenter在Android中的应用

这篇文章是我学习MVP模式时翻译的,原文是Konstantin Mikheev所写,传送门. 因英语水平有限,翻译的很生硬,基本靠Google,请见谅.以下是译文. 这篇文章我会通过一个最简单的例子去一步步介绍MVP模式在Android中的最佳实践.同时我也会介绍一个使MVP模式在Android开发中变简单的library. 简单?怎么才能从中获益呢? 什么是MVP View层是用来显示数据和相应数据操作的.在Android中,它可能是Activity,Fragment,View或者Dialog

SSH----MVC框架模式与分层架构

MVC框架模式 MVC框架模式是web开发中一种软件设计典范,他的全名是(Model -View -Controller),是模型(model)--视图(view)--控制器(controller)的缩写,用一种业务逻辑.数据控制.界面显示分离的方式组织代码, 实现代码的模块化设计. Model,意为数据模型,该块封装了对数据的处理(底层封装了对数据库的操作) Controller,意为控制器,该块获取用户输入,并控制数据到Model模块进行逻辑处理. View,意为界面,该块从model模块获

android中MVC,MVP和MVVM三种模式详解析

我们都知道,Android本身就采用了MVC模式,model层数据源层我们就不说了,至于view层即通过xml来体现,而 controller层的角色一般是由activity来担当的.虽然我们项目用到了MVP模式,但是现在人们并没有总结出一种规范,所以MVP模式的写法并不统一,而至于MVVM模式看网上的呼声似乎也是赞同和拍砖的参半,所以对于这几种模式我也不发表意见了,适合自己的才是最好的.下面是我看到的关于这几种模式的几篇文章,整合了一下分享给大家. ----------------------