进阶之路:MVP+Retrofit+RxJava组合使用

版权声明:本文为申然哥哥原创文章。原文链接:http://blog.csdn.net/qq_27778869/article/details/52121208



通过这几天对这三者开发中的使用,今天准备做一个小的总结,帮助需要爬坑的"道友"!
1.## 首先先分别介绍一下这三个是什么东东 ##
    1.MVP:MVP是基于MVC的改进,相信大家都是从MVC走过的,可能很多人还会在项目中使用MVC,我们传统的MVC 中xml布局充当就是视图层(View) ,业务层兼模型层的一些业务的处理需要在我们Activity 或Fragment中进行处理然后更新视图层,由于xml定义好的布局,一旦加载之后,只能通过动态更新,那么视图层和Model就建立了联系,因此二者的耦合度就提高了,那么一旦修改了其中的一个就有可能对另一产生影响,这很不利于我们后期的项目维护。同时所有的操作在我们的Controller中进行处理,我们的Controller就会显得十分的臃肿,可阅读性就降低了,对我们后期的项目维护成本提高了不少,很多时候你需要和团队一起开发一个项目,如果你的同事有一天在你请假或者想修改功能的时候发现一个Activity都有上前行甚至更多的时候,他开始慌了,他慌的时候如果还找到你的话,你可能也慌了。有了MVP之后,妈妈再也不用担心我会慌了!
    ## 我们的MVP模式来了 ##在MVP中model层依然不变,只不过之前充当Controller的Activity或者Fragment就变身为了View层,而业务逻辑的实现是在我们的Presenter中。简单介绍完了MVP,光说不练,一点效果都没有的,下面我们来进行MVP的三部曲:
        本次案例是在进入程序的时候访问服务器的指定接口来获取当前服务器的apk的版本号,通过对比和当前应用程序的版本号,如果有新版本弹出一个土司提示用户更新,功能就这么简单,下面开始码代码:
        1.视图层需要哪些更新UI的操作?可能大家会好奇我为什么会问这个,这里我留下一个悬念,待会给大家细讲。这个问题的答案是弹出一个土司提示用户更新。
        2.怎么进行更新UI前的操作?
        3.何时告知视图层进行UI更新?
    结合上面的三个问题:我们根据需求设计代码:
        1>定义一个MvpView的接口 
public Interface MvpView {
//提示更新
void showMessage();

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
        2>定义一个Model类
public class MvpModel{
  /*从服务器获取的apk版本*/
    private String newApkVersion;
//这里我就随便给出一个,正确与否我就不得而知 这里面需要注意的query是跟上请求的参数,通过GET方法来请求的 ,你可能这会问我,不是说不知道正不正确的吗,那还解释这么多?不好意思哈,我这里说明好是为了下面讲到Retrofit 做铺垫的
    public static final String GET_NEW_VER_URL="http://192.168.1:8080/app/index/type?version=query";
    public String getNewApkVersion() {
        return newApkVersion;
    }

    public void setNewApkVersion(String newApkVersion) {
        this.newApkVersion = newApkVersion;

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
        3>定义一个基类BasePresenter(当然大家也可以不用这么做)
public abstract class BasePresenter<T> {

    /*这个基类的Presenter 主要的作用就是将当前Presenter持有的view 在合适的时候给清除掉*/
    public T mView ;
    public void attach(T mView){

        this.mView=mView;


    }


    public void dettach(){

        mView=null;

 }

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
        4>定义一个实际操作的MvpPresenter
public class MvpPresenter extends BasePresenter<MvpView> {
    private MvpModel mMvpModel;
    private Context mContext;
    private RequestQueue mRequestQueue;
    //这里重写当前的构造函数 因为我们需要获取程序的版本,因此需要一个上下文对象 
    public MvpPresenter (Context mContext) {
        this.mContext = mContext;
        //当前的Mvp模式的讲解我是采用Volley进行网络请求的所以 就封装了一个VolleyManager用于获取唯一的RequestQueue对象
        mRequestQueue = VolleyManager.getInstance(mContext).getRequestQueue();
        //对业务层初始化为后面获取的apk版本进行存放
        mUpdateModel = new MvpModel();
   }
   //由于逻辑处理放到我们的Presenter中了,因此我们需要将在Activity的onResume 时候进行版本的检查
   public void onResume(){


    }

    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
        5>开始视图层的构建了不过在之前我们先创建一个BaseMvpActivity 用于统一化管理我们的MVP模式的Activity的构建
public abstract class BaseMvpActivity<V,T extends BasePresenter<V> > extends AppCompatActivity {



 /*定义一个Presenter 用于解绑持有的View
    *
    * 在onCreate进行初始化Presenter的操作
    * 在onResume中进行绑定
    * 在onDestroy 中进行解绑
    *
    * */
    public T presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        presenter=initPresenter();

    }

    @Override
    protected void onResume() {
        super.onResume();
        presenter.attach((V)this);
    }

     @Override
        protected void onDestroy() {
        super.onDestroy();
        presenter.dettach();
     }

    /* 这里是适配为不同的View 装载不同Presenter*/
    public abstract T initPresenter();


}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
        6>正式写我们的应用Activity了(当前activity的布局中仅有一个TextView)
public class MvpActivity extends BaseMvpActivity<MvpView,MvpPresenter> implements MvpView{
    @Bind(R.id.tvShow)
    TextView tvMsg;
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_update);
        ButterKnife.bind(this);
       }
    @Override
    protected void onResume() {
        super.onResume();
       presenter.onResume();
    }
     @Override
    public MvpPresenter initPresenter() {
        return new MvpPresenter (getApplicationContext());
    }
     @Override

    public void showMessage(){

    tvMsg.setText("有新版本需更新!");

    Toast.makeText(getApplicationContext(),"更新版本啦",Toast.LENGTH_LONG).show();


    }








}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
        7>看到上面的MvpActivity 是不是觉得代码很清爽,那还不是把业务处理的逻辑丢给了 Presenter了,好了我们来具体看看MvpPresenter是怎么写
//在前面贴出的代码中添加
pulic void onResume(){

getVerFromServer();


}
private void getVerFromServer(){

    JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.GET, MvpModel.GET_NEW_VERSION ,null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                Log.e("请求版本返回结果为:",response.toString());

                                try {
                    mUpdateModel.setNewApkVersion(response.getJSONObject("data").getString("version"));
            //如果从服务器获取的版本和当前的版本相同,就可提示用户了
            if(mUpdateModel.getNewApkVersion.equals(getCurrentVer())){
             //这里就是合适的更新UI时间,通过这里把更新的实际传递出去
                mView.showMessage();
                                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        jsonRequest.setTag("getVer");
        mRequestQueue.add(jsonRequest);


}
private String getCurrentVer(){
 String verName="";
        try {
            verName=mContext.getPackageManager().getPackageInfo(context.getPackageName(),0).versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        Log.e("apkVer",verName);
        return verName;

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
    2.##Retrofit的简单使用介绍 ##
    相信大家在开发过程中被这个字眼给冲击过不少次,具体Retrofit 是什么这里我就不详细介绍了,如果有不明白的读者可以看看我之前的一篇的文章对Retrofit有简单的介绍,但是这里我们只针对它的简单应用来讲解:
        1>我们首先需要创建一个接口如RetrofitCall,因为Retrofit是通过注解的形式构建方法的 下面我们来 写一下:
public interface RetrofitCall{
    // 我们把之前定义好的api接口 拿来  http://192.168.1:8080/app/index/type?version=query
    //这里我先简单给大家介绍一下 Retrofit 请求网络的接口形式要满足RESTful 形式(有不了解的可自填坑) 不够构成一般是这样的[协议类型:][//主机地址加端口(或者域名)][具体目录][请求参数]
    //所以这个接口的具体目录(path)为app/index/type 也就是下面这个GET注解中应该填入的
    @GET("app/index/type")
    Call<VersionBean> getVer(@Query(version) String ver); 
    //如果有读者不知道这个VersionBean怎么生成的可以查看我的博客有一篇讲Retrofit的 其实就是利用GSONFromat 来实现的

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
        2>注册网络访问(这里的代码是在Presenter实现的)
Retrofit mRetrofit =new Retrofit.Builder()
                    //这里为主机加端口(或域名)
                  .baseUrl("http://192.168.1:8080/")
                  .clent(new OkHttpClient())
                  .addConverterFactory(GsonConverterFactory.create())
                  .build();

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
        3>创建自定义接口实例并执行异步网络请求
RetrofitCall call=mRetrofit.create(RetrofitCall.class);
//这里需要把请求的参数填入
Call<VersionBean> myCall=call.getVer("1");
//异步执行
maCall.enqueue(new Callback<VersionBean>(){
@Override
       public void onResposne(Call<VersionBean>call,retrofit2.Response<VersionBean> response)    {


        if(response.body().getData().getVersion().equals(getCurrentVe   r())){

          mView.showMessage();
          }
}
            @Override
            public void onFailure(Call<VersionBean> call, Throwable t) {
            Log.e("callerro+"------------>"+t);
            }

});

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
    3.## 通过RxJava对上面Retrofit 的改进 ##
    RxJava 是一个异步操作的库,主要采用的观察者模式,在这里我只是简单的介绍,需要详细了解可以参考扔物线的这篇[给Android开发工程师的一篇关于RxJava的详解](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/1012/3572.html?from=timeline&isappinstalled=0#toc_1)
    在这里我就不作过多的篇幅来介绍了,我们来演示RxJava依靠Retrofit的改进上面的代码,我们在RetrofitCall中添加一个新的注解
@GET("app/index/type")
Observable<VersionBean> getVerByRxJavaWithRetrofit(@Query("version") String ver);
 
 
  • 1
  • 2
  • 1
  • 2
    接着在Presenter中填入如下的方法:
private void requestDataByRxJavaWithRetrofit(){
    Retrofit mRxjavaRetrofit= new Retrofit.Builder()
                        .baseUrl("http://192.168.1:8080/")
                        //由于需要转为Observable 需要添加RxJavaCallAdapterFactory
                        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
    RetrofitCall call= mRxjavaRetrofit.create(RetrofitCall.class);
    call.getVerByRxJavaWithRetrofit(""1)
    //指定时间消费在主线程
    .observeOn(AndroidSchedulers.mainThread())
    //事件产生在新线程
    .subscribeOn(Schedulers.newThread())
    //指定一个观察者
    .subscribe(new Observer<Version>(){
                    @Override
                    public void onCompleted() {

                    mView.showMessage();
                      }

                    @Override
                    public void onError(Throwable e) {

                    }
                    /*这个时候是订阅者需要跟新UI的时间了通知它更新*/
                    @Override
                    public void onNext(LogoBean logoBean) {
                        /*这里先不做判断*/

                    }


    }       );

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
4## 总结 ##
上面对这三者的结合使用有了一个直观的介绍,其实MVP模式可以理解为 更新UI需要什么操作,什么时候开始更新UI,怎么更新UI;而我们的MVP模式就是把这三种状态巧妙地分开,因此会让思路显得很清晰,而RxJava 正式基于这种设计,被观察者通过被订阅的形式在自己有新动态的时候告知观察者我改变了,剩下的就交给观察者做自己应该做的事情了!这样的设计模式很符合我们需求,也很利于团队开发,换个模式你会觉得效率大大提高,让我们一起加入MVP+RxJava+Retrofit的队列之中吧! 
MVP(Model View Presenter)其实就是一种项目的整体框架,能让你的代码变得更加简洁,说起框架大家可能还会想到MVC、MVVM。由于篇幅原因,这里我们先不讲MVVM,先来看一下MVC。其实Android本身就采用的是MVC(Model View Controllor)模式、其中Model指的是数据逻辑和实体模型;View指的是布局文件、Controllor指的是Activity。对于很多Android初学者可能会有这样的经历,写代码的时候,不管三七二十一都往Activity中写,当然我当初也是这么干的,根本就没有什么框架的概念,只要能实现某一个功能就很开心了,没有管这么多。当然项目比较小还好,一旦项目比较大,你会发现,Activity所承担的任务其实是很重的,它既要负责页面的展示和交互,还得负责数据的请求和业务逻辑之类的工作,相当于既要打理家庭,又要教育自己调皮的孩子,真是又当爹又当妈。。。那该怎么办呢?这时候Presenter这个继父来到了这个家庭。Presenter对Activity说,我来了,以后你就别这么辛苦了,你就好好打理好View这个家,我专门来负责教育Model这孩子,有什么情况我会向你反映的。这时Activity流下了幸福的眼泪,从此,Model、View(Activity)、Presenter一家三口过上了幸福的生活。。。好了磕个药继续,由于Presenter(我们自己建的类)的出现,可以使View(Activity)不用直接和Model打交道,View(Activity)只用负责页面的显示和交互,剩下的和Model交互的事情都交给Presenter做,比如一些网络请求、数据的获取等,当Presenter获取到数据后再交给View(Activity)进行展示,这样,Activity的任务就大大减小了。这便是MVP(Model 还是指的数据逻辑和实体模型,View指的是Activity,P就是Presenter)框架的工作方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值