MVP模式原理分析 以及两个实例带你飞_c++mvp原理_Android_Developer_M的博客-程序员秘密

技术标签: java  Android  

本blog介绍mvp模式的特点与优点,为了方便理解 举了用mvp模式实现的两个例子,例一偏向简单用于原理说明,例二应用现在比较火的Retrofit和RXJava进行网络数据请求的mvp模式实例。


1、MVP模式:

 

2、MVP模式  VS  MVC模式

(1)各个层之间通过接口协议进行沟通。

(2)View和Model不再进行直接交互

 

3、MVP优势:

       (1)View和Model之间的耦合度降低,使各自更关注自身业务。

       (2)便于单元测试。

       (3)代码复用率提高。

       (4)代码框架更适用于快速迭代开发。

4、-----------------------------实例1

     

     项目结构:


View层:

public class BaseViewActivity extends AppCompatActivity implements BaseView{
    private BasePresenterImpl mPresenter;
    boolean flag;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPresenter = new BasePresenterImpl(this);

        Log.e("JS","进入 view 层  1");
        //开始请求服务
        mPresenter.loadData();
        Log.e("JS","进入 view 层  2");
        //加载完成
        mPresenter.loadResult();
    }

    @Override
    public void loading() {
        Log.e("JS","开启  进入view层 iterface 事件");
    }

    @Override
    public void cancelLoading() {
        Log.e("JS","结束  进入view层 iterface 事件");
    }
}

//UI逻辑接口,一般由activity、fragment实现
public interface BaseView {
    //显示加载进度
    void loading();

    //隐藏加载进度
    void cancelLoading();
}

presenter层:

public class BasePresenterImpl implements BasePresenter{
    private BaseView mView;
    private BaseModel mModel;

    public BasePresenterImpl(BaseView view){
        mModel = new BaseModelimpl();
        this.mView = view;
    }

    // 调用view层和model层来 加载数据
    public void loadData(){
        Log.e("JS","model/view------->presenter ");
        mView.loading();//访问view层
        mModel.RequestService();//访问model层

        Log.e("JS","-----可得到 view和model return 的数据-------");
    }




    @Override
    public void loadResult() {
        Log.e("JS","presenter --------->  view ");
        mView.cancelLoading();
    }
}

/**处理业务逻辑
 * Created by apple on 17/4/27.
 */

public interface BasePresenter {
    //加载数据结果
    void loadResult();
}

Model层:

public class BaseModelimpl implements BaseModel {
    @Override
    public void RequestService() {
        Log.e("JS","开启  进入model层     interface");
    }
}

public interface BaseModel {
    //请求服务器
    void RequestService();

}


打印信息:





实例2-----------------

retrofit和rxJava结合的mvp实例

1、view层接口

import com.example.apple.retrofit.MVP.bean.IpBean;

/**
 * Created by apple on 17/5/4.
 */

public interface interView {
    public void showInfo(IpBean ipBean);
    public void showError(Throwable e);
}

view层activity

import com.example.apple.retrofit.MVP.bean.IpBean;
import com.example.apple.retrofit.MVP.presenter.Presenter;
import com.example.apple.retrofit.MVP.presenter.interPresenter;
import com.example.apple.retrofit.R;

/**
 * Created by apple on 17/5/4.
 */

public class MainActivity extends Activity implements interView{
    private TextView ipInfo;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ipInfo = (TextView) findViewById(R.id.ipInfo);
        interPresenter presenter = new Presenter(this);
        presenter.queryIpInfo("121.33.6.228");//调用presenter层的接口方法
    }

    @Override
    public void showInfo(IpBean ipBean) {
        String aa = ipBean.area+ipBean.city+ipBean.country+ipBean.ip+ipBean.region;
        Log.e("jj",aa);
        ipInfo.setText(aa);
    }

    @Override
    public void showError(Throwable e) {

    }
}

2、presenter层接口

public interface interPresenter {
    public void queryIpInfo(String ip);
}

presenter实现类

public class Presenter implements interPresenter{
    //在presenter层,引入model层和view层。
    private interView viewActivity;
    private interModel model;

    public Presenter(MainActivity viewActivity){
        this.viewActivity = viewActivity;
        model = new Model();
    }

    @Override
    public void queryIpInfo(String ip) {
        //观察者位于presenter层,通知主线程

        Subscriber<ApiBean<IpBean>> mySubscriber = new Subscriber<ApiBean<IpBean>>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {
                viewActivity.showError(e);
            }

            @Override
            public void onNext(ApiBean<IpBean> ipBeanApiBean) {
                //获取来自被观察者model层传来的ipBeanApiBean,并调用view层方法
                viewActivity.showInfo(ipBeanApiBean.data);
            }
        };
        model.queryIpInfo(ip,mySubscriber);//调用model接口方法
    }
}

3、model层接口

public interface interModel {
    public void queryIpInfo(String ip, Subscriber<ApiBean<IpBean>> subscriber);
}

model层retrofit请求接口(此请求采用get方式)

public interface InterfRetrofit {
    @GET("service/getIpInfo.php")
    Call<ApiBean<IpBean>> getMessage(@Query("ip") String ip);
}

model层实现类

public class Model implements interModel{
    @Override
    public void queryIpInfo(final String ip, Subscriber<ApiBean<IpBean>> subscriber) {
        //被观察者做耗时操作,位于model层
        Observable<ApiBean<IpBean>> myObserverble =
                Observable.create(new Observable.OnSubscribe<ApiBean<IpBean>>() {
                    @Override
                    public void call(Subscriber<? super ApiBean<IpBean>> subscriber) {
                        //在rxjava的observable中,添加一个retrofit,进行网络请求 具体耗时操作由它执行
                        String URL_BASE = "http://ip.taobao.com";
                        Retrofit retrofit = new Retrofit.Builder()
                                .baseUrl(URL_BASE)
                                .addConverterFactory(GsonConverterFactory.create())
                                .build();
                        InterfRetrofit interfRetrofit = retrofit.create(InterfRetrofit.class);
                        Call<ApiBean<IpBean>> call = interfRetrofit.getMessage(ip);
                        try {
                            Response<ApiBean<IpBean>> response = call.execute();
                            ApiBean<IpBean> apiResponse = response.body();
                            //将apiResponse传给观察者presenter
                            subscriber.onNext(apiResponse);
                        } catch (IOException e) {
                            e.printStackTrace();
                            subscriber.onError(e);
                        }finally {
                            subscriber.onCompleted();
                        }

                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        myObserverble.subscribe(subscriber);
    }
}

4、数据解析bean层

public class ApiBean<T> implements Serializable {
    //结果
    public int code;
    //数据
    public T data;
}

import com.google.gson.annotations.SerializedName;

public class IpBean {
    //国家
    public String country;
    //国家代码
    @SerializedName("country_id")
    public String countryId;
    //地区
    public String area;
    //地区代码
    @SerializedName("area_id")
    public String areaId;
    //省份
    public String region;
    //省份代码
    @SerializedName("region_id")
    public String regionId;
    //城市
    public String city;
    //城市代码
    @SerializedName("city_id")
    public String cityId;
    //区
    public String county;
    //区号
    @SerializedName("county_id")
    public String countyId;
    //运营商
    public String isp;
    //运营商代码
    @SerializedName("isp_id")
    public String ispId;
    //IP地址
    public String ip;
}




版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/j18874964028sss/article/details/70877455

智能推荐

一篇文章了解什么是增长黑客_Hunter-狩猎者的博客-程序员秘密

最近在Kindle上读了范冰的《增长黑客》,对增长黑客有了更系统的了解。联想到我自己的微信公众号hacker-thinking和独立博客blog.coderzh.com,我也在苦苦寻找用户增长的终极奥义。我也尝试过各种SEO(搜索引擎优化),比如规范链接地址、nofollow防止权重降低、提供sitemap、增加关键词、规范robots.txt、加快访问速度、增加反向链接等等。肯定有人会说,这些东

SpringDataJpa的扩展_spring jpa扩展_极乐码农的博客-程序员秘密

SpringDataJpa的扩展继承JpaSpecificationExecutor继承JpaSpecificationExecutordao层public interface PersonDao extends JpaRepository&lt;Person,Integer&gt;, JpaSpecificationExecutor&lt;Person&gt; {}案例测试1单条件 /* * 根据条件,查询单个对象 * */ @Test publ

Oracle修改字段类型Sql --ORA-01439_oracle pl/sql修改数据类型_璀璨_的博客-程序员秘密

有一个表名为tb,字段段名为name,数据类型nchar(20)。1、假设字段数据为空,则不管改为什么字段类型,可以直接执行:alter table tb modify (name nvarchar2(40));2、假设字段有数据,则改为varchar2(40)执行时会弹出:“ORA-01439:要更改数据类型,则要修改的列必须为空”,这时要用下面方法来解决这个问题:--修改原字段...

Elasticsearch 7.X RESTful 风格 索引、文档、映射操作_es7.x 索引的映射_小毕超的博客-程序员秘密

一、ElasticsearchElasticsearch (ES)是一个基于Lucene构建的开源、分布式、RESTful 接口全文搜索引擎。Elasticsearch 还是一个分布式文档数据库,其中每个字段均是被索引的数据且可被搜索,它能够扩展至数以百计的服务器存储以及处理PB级的数据。它可以在很短的时间内在储、搜索和分析大量的数据。它通常作为具有复杂搜索场景情况下的核心发动机。Elasticsearch就是为高可用和可扩展而生的。可以通过购置性能更强的服务器来完成。在本专栏的前几篇文章中我们介绍过

智能优化算法———差分演化算法(C++)_差分进化算法求解实数优化问题_洗头冠军的博客-程序员秘密

差分演化算法(Differential Evolution)是曾经一度非常热门的算法,该算法简单易用,收敛速度快。这篇文章对其进行总结。算法简介所谓的演化算法是一种自适应,并行的全局优化算法,还包括遗传算法等。差分演化算法与其他演化算法的最大区别在与差分变异算子的应用。差分演化算法主要用于求解实数优化问题,一般不用于求解离散问题。算法流程算法流程图如下。...

随便推点

anddisign 2.x table无法引入_React 17.0.0-rc.2 版本发布,引入全新的 JSX 转换_weixin_39592137的博客-程序员秘密

北京时间 9 月 23 日凌晨,React 团队发布了关于全新 JSX 转换的博客,同时发布了 React 17 的 RC 版本,新的 JSX 转换不再依赖 React 环境,在转换时会自动引入新的 runtime。 原文链接:https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html 作者:Luna Ru...

第2.3章 过滤器模式+模板模式设计八字命理的十神分析_warrah的博客-程序员秘密

如果单独看《Head First 设计模式》中介绍的23种设计模式,单例模式和工厂模式普通开发工程师能够理解,其他模式UML类画的就较为抽象,实现起来并没有那么复杂,只不过要用图形来展现,显的专业的话,就有些麻烦。但是80%的开发工程师能够容易理解吗,我认为大多数人知道继承和实现,就通过这两种方式组合,已经说命了很多问题。古人发明四柱八字,子平讲十神定位,如果通过计算机来实现子平的模型,按照梁湘...

支付宝”向他付款”,定额付款收款链接生成_支付宝付款链接生成_ios and Android的博客-程序员秘密

很多博客文末都会有支付宝&quot;向他付款&quot;链接,点击进去后生成定额付款收款链接。这个是怎么实现的呢,其实很简单。将下面的代码复制到博客html下,保存即可。&amp;lt;div id=&quot;zanzhu&quot;&amp;gt;&amp;lt;center&amp;gt;&amp;lt;form class=&quot;form123&quot; accept-charset=&quot;GBK&quot; action=&quot;https://shenghuo.alipay.c

python重启路由器_利用python重启路由器_weixin_39991926的博客-程序员秘密

家里用的是D-link路由器,不超过100块那种。由于路由器年代久远,偶尔会抽风连不了外网,这时就需要重启路由器。一般常规的做法一是断电重启;二是登陆路由器系统设置选项进行重启。有时路由器离电脑太远了不想跑过去断电,登陆路由器又有点烦锁,什么打开浏览器输入用户名密码找到系统设置选项再点击重启。于是就设想写个python脚本,直接双击或者快捷键打开马上重启路由器。用python来模拟人员登陆路由器设...

HDLBits刷题_Verilog Language_Bcdadd100_bcd add100_Little_Engineer456的博客-程序员秘密

You are provided with a BCD one-digit adder namedbcd_faddthat adds two BCD digits and carry-in, and produces a sum and carry-out.module bcd_fadd { input [3:0] a, input [3:0] b, input cin, output cout, output [3:0] sum );In..

verilog笔记_generate_MaxAlbert的博客-程序员秘密

verilog笔记_generate使用generate时必须先在genvar中声明循环中使用的索引变量名,然后才能使用它。genvar声明的索引变量被用作整数用来判断generate循环。Verilog中generate循环中的generate块最好命名。通常,generate for循环和普通 for循环之间的主要区别在于generate for循环正在为每次迭代生成一个实例。例题Adder100i - HDLBits (01xz.net)代码module top_module(

推荐文章

热门文章

相关标签