当前位置: 移动技术网 > IT编程>移动开发>Android > 深入浅出RxJava+Retrofit+OkHttp网络请求

深入浅出RxJava+Retrofit+OkHttp网络请求

2019年07月24日  | 移动技术网IT编程  | 我要评论

郎溪县卫生局,舞浜朱里,叶选平儿子

浅谈rxjava+retrofit+okhttp 封装使用 之前发出后收到很多朋友的关注,原本只是自己学习后的一些经验总结,但是有同学运用到实战当中,这让我很惶恐,所有后续一直更新了很多次版本,有些地方难免有所变动导致之前的博客有所出入,正好最近受到掘金邀请内测博客,所以决定重新写一版,按照最后迭代完成的封装详细的讲述一遍,欢迎大家关注!

注意:由于本章的特殊性,后续文章比较长而且复杂,涉及内容也很多,所以大家准备好茶水,前方高能预警。

简介:

retrofit: retrofit是square 公司开发的一款正对android 网络请求的框架。底层基于okhttp 实现,okhttp 已经得到了google 官方的认可。

okhttp: 也是square 开源的网络请求库

rxjava:rxjava 在 github 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the java vm"(一个在 java vm 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 rxjava ,概括得非常精准。总之就是让异步操作变得非常简单。

各自的职责:retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,okhttp 负责请求的过程,rxjava 负责异步,各种线程之间的切换。

rxjava + retrofit + okhttp 已成为当前android 网络请求最流行的方式。

封装成果

封装完以后,具有如下功能:

    1.retrofit+rxjava+okhttp基本使用方法
    2.统一处理请求数据格式
    3.统一的progressdialog和回调subscriber处理
    4.取消http请求
    5.预处理http请求
    6.返回数据的统一判断
    7.失败后的retry封装处理
    8.rxlifecycle管理生命周期,防止泄露

实现效果:

具体使用

封装后http请求代码如下

//  完美封装简化版
  private void simpledo() {
    subjectpost postentity = new subjectpost(simpleonnextlistener,this);
    postentity.setall(true);
    httpmanager manager = httpmanager.getinstance();
    manager.dohttpdeal(postentity);
  }

  //  回调一一对应
  httponnextlistener simpleonnextlistener = new httponnextlistener<list<subject>>() {
    @override
    public void onnext(list<subject> subjects) {
      tvmsg.settext("已封装:\n" + subjects.tostring());
    }

    /*用户主动调用,默认是不需要覆写该方法*/
    @override
    public void onerror(throwable e) {
      super.onerror(e);
      tvmsg.settext("失败:\n" + e.tostring());
    }
  };

是不是很简单?你可能说这还简单,好咱们对比一下正常使用retrofit的方法

/** 
  * retrofit加入rxjava实现http请求 
  */ 
  private void onbutton9click() { 
    //手动创建一个okhttpclient并设置超时时间 
    okhttp3.okhttpclient.builder builder = new okhttpclient.builder(); 
    builder.connecttimeout(5, timeunit.seconds); 

    retrofit retrofit = new retrofit.builder() 
        .client(builder.build()) 
        .addconverterfactory(gsonconverterfactory.create()) 
        .addcalladapterfactory(rxjavacalladapterfactory.create()) 
        .baseurl(httpmanager.base_url) 
        .build(); 

/    加载框 
    final progressdialog pd = new progressdialog(this); 

    httpservice apiservice = retrofit.create(httpservice.class); 
    observable<retrofitentity> observable = apiservice.getallvedioby(true); 
    observable.subscribeon(schedulers.io()).unsubscribeon(schedulers.io()).observeon(androidschedulers.mainthread()) 
        .subscribe( 
            new subscriber<retrofitentity>() { 
              @override 
              public void oncompleted() { 
                if (pd != null && pd.isshowing()) { 
                  pd.dismiss(); 
                } 
              } 

              @override 
              public void onerror(throwable e) { 
                if (pd != null && pd.isshowing()) { 
                  pd.dismiss(); 
                } 
              } 

              @override 
              public void onnext(retrofitentity retrofitentity) { 
                tvmsg.settext("无封装:\n" + retrofitentity.getdata().tostring()); 
              } 

              @override 
              public void onstart() { 
                super.onstart(); 
                pd.show(); 
              } 
            } 

        ); 
  }

可能你发现确是代码有点多,但是更加可怕的是,如果你一个activity或者fragment中多次需要http请求,你需要多次重复的写回调处理(一个回到就有4个方法呀!!!!反正我是忍受不了),而且以上处理还没有做过多的判断和错误校验就如此复杂!~好了介绍完了,开始咱们的优化之路吧!

项目结构:

retrofit

咱家今天的主角来了,咱们也深入浅出一下了解下retrofit使用,前方高能,如果你是深度retrofit选手请直接跳过本节!!!

1.首先确保在androidmanifest.xml中请求了网络权限

<uses-permission android:name="android.permission.internet"/>

2.在app/build.gradle添加引用

 /*rx-android-java*/
  compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
  compile 'com.trello:rxlifecycle:1.0'
  compile 'com.trello:rxlifecycle-components:1.0'
  /*rotrofit*/
  compile 'com.squareup.retrofit2:retrofit:2.1.0'
  compile 'com.squareup.retrofit2:converter-gson:2.0.0'
  compile 'com.google.code.gson:gson:2.8.0'

3.常用注解

这里介绍一些常用的注解的使用

  1. @query、@querymap:用于http get请求传递参数
  2. @field:用于post方式传递参数,需要在请求接口方法上添加@formurlencoded,即以表单的方式传递参数
  3. @body:用于post,根据转换方式将实例对象转化为对应字符串传递参数.比如retrofit添加gsonconverterfactory则是将body转化为gson字符串进行传递
  4. @path:用于url上占位符
  5. @part:配合@multipart使用,一般用于文件上传
  6. @header:添加http header
  7. @headers:跟@header作用一样,只是使用方式不一样,@header是作为请求方法的参数传入,@headers是以固定方式直接添加到请求方法上

retrofit基本使用:

首先给定一个测试接口文档,后面的博客中我们都是用这个接口调试

/** 
 * @api  videolink  50音图视频链接 
 * @url  http://www.izaodao.com/api/appfiftytonegraph/videolink 
 * @method post 
 * @param once_no bool(选填,ture无链接) 一次性获取下载地址 
 * @return json array( 
 * ret:1成功,2失败 
 * msg:信息 
 * data:{ 
 *    name:视频名称 
 *    title:标题 
 * } 
 )

1.初始化retrofit

要向一个api发送我们的网络请求 ,我们需要使用retrofit builder类并指定service的base url(通常情况下就是域名)。

string base_url = " http://www.izaodao.com/api/" 
  retrofit retrofit = new retrofit.builder() 
      .baseurl(base_url) 
      .addconverterfactory(gsonconverterfactory.create()) 
      .build();

2.设置接口service

注意到每个endpoint 都指定了一个关于http(get, post, 等等。) 方法的注解以及用于分发网络调用的方法。而且这些方法的参数也可以有特殊的注解。

/** 
 * 接口地址 
 * created by wzg on 2016/7/16. 
 */ 
public interface myapiendpointinterface { 
  @post("appfiftytonegraph/videolink") 
  call<retrofitentity> getallvedio(@body boolean once_no)       
}

3.得到call然后同步处理处理回调:

myapiendpointinterface apiservice = retrofit.create(myapiendpointinterface.class); 
call<retrofitentity> call = apiservice.getallvedio(true); 
call.enqueue(new callback<retrofitentity>() { 
  @override 
  public void onresponse(response<retrofitentity> response, retrofit retrofit) { 
    retrofitentity entity = response.body(); 
    log.i("tag", "onresponse----->" + entity.getmsg()); 
  } 

  @override 
  public void onfailure(throwable t) { 
    log.i("tag", "onfailure----->" + t.tostring()); 

  } 
});

这就是简单的retrofit使用步骤,接下来我们结合rxjava讲述

retrofit+rxjava基本使用

对比之前的retrofit使用

1.在于我们需要修改service接口返回信息我们需要返回一个observable对象

@post("appfiftytonegraph/videolink") 
observable<retrofitentity> getallvedioby(@body boolean once_no);

2.然后初始化retrofit需要添加对rxjava的适配,注意一定要retrofit2才有这个功能哦

retrofit retrofit = new retrofit.builder() 
        .client(builder.build()) 
        .addconverterfactory(gsonconverterfactory.create()) 
        .addcalladapterfactory(rxjavacalladapterfactory.create()) 
        .baseurl(httpmanager.base_url) 
        .build();

3.回调通过rxjava处理

httpservice apiservice = retrofit.create(httpservice.class); 
    observable<retrofitentity> observable = apiservice.getallvedioby(true); 
    observable.subscribeon(schedulers.io()).unsubscribeon(schedulers.io()).observeon(androidschedulers.mainthread()) 
        .subscribe( 
            new subscriber<retrofitentity>() { 
              @override 
              public void oncompleted() { 
              } 

              @override 
              public void onerror(throwable e) {                
              } 

              @override 
              public void onnext(retrofitentity retrofitentity) { 
                tvmsg.settext("无封装:\n" + retrofitentity.getdata().tostring()); 
              }              
            } 

        );

简单的rxjava集合retrofit的使用就介绍完了,同样的可以发现使用起来很多重复性的代码,而且使用也不是那么简单,所以才有了下面的封装

retrofit+rxjava进阶封装之路

先来一张流程图压压惊

请求数据封装

1.参数

首先需要封装的使我们的数据类,在数据类中需要封装请求中用到的相关数据的设置,比如请求参数、方法、加载框显示设置等等

public abstract class baseapi<t> implements func1<baseresultentity<t>, t> {
  //rx生命周期管理
  private softreference<rxappcompatactivity> rxappcompatactivity;
  /*回调*/
  private softreference<httponnextlistener> listener;
  /*是否能取消加载框*/
  private boolean cancel;
  /*是否显示加载框*/
  private boolean showprogress;
  /*是否需要缓存处理*/
  private boolean cache;
  /*基础url*/
  private string baseurl="http://www.izaodao.com/api/";
  /*方法-如果需要缓存必须设置这个参数;不需要不用設置*/
  private string mothed;
  /*超时时间-默认6秒*/
  private int connectiontime = 6;
  /*有网情况下的本地缓存时间默认60秒*/
  private int cookienetworktime=60;
  /*无网络的情况下本地缓存时间默认30天*/
  private int cookienonetworktime=24*60*60*30;
}

注释很详细,这里不具体描述了,由于这里是最后封装完成以后的代码,所以有些内容本章还会部分不会涉及,因为功能太多,还是按照一开始的博客章节讲解。

2.抽象api接口

  /**
   * 设置参数
   *
   * @param retrofit
   * @return
   */
  public abstract observable getobservable(retrofit retrofit);

通过子类也即是我们的具体api接口,通过getobservable实现service中定义的接口方法,例如:

public class subjectpostapi extends baseapi {
   xxxxxxx
   xxxxxxx

 @override
  public observable getobservable(retrofit retrofit) {
    httppostservice service = retrofit.create(httppostservice.class);
    return service.getallvediobys(isall());
  }
}

通过传入的retrofit对象,可以随意切换挑选service对象,得到定义的注解方法,初始完成以后返回observable对象。

3.结果判断

这里结合rxjava的map方法在服务器返回数据中,统一处理数据处理,所以baseapi<t> implements

func1<baseresultentity<t>, t>,后边结合结果处理链接起来使用
  @override
  public t call(baseresultentity<t> httpresult) {
    if (httpresult.getret() == 0) {
      throw new httptimeexception(httpresult.getmsg());
    }
    return httpresult.getdata();
  }

由于测试接口,也是当前我们公司接口都是有统一规则的,想必大家都有这样的接口规则,所以才有这里的统一判断,规则如下:

 * ret:1成功,2失败 
 * msg:信息 
 * data:{ 
 *    name:视频名称 
 *    title:标题 
 * }

其实上面的接口文档中就介绍了,统一先通过ret判断,失败显示msg信息,data是成功后的数据也就是用户关心的数据,所以可封装一个结果对象baseresultentity.

4.结果数据

/**
 * 回调信息统一封装类
 * created by wzg on 2016/7/16.
 */
public class baseresultentity<t> {
  // 判断标示
  private int ret;
  //  提示信息
  private string msg;
  //显示数据(用户需要关心的数据)
  private t data;


  xxxxx get-set xxxxx
}

这里结合baseapi的func1判断,失败直接抛出一个异常,交个rxjava的onerror处理,成功则将用户关心的数据传给gson解析返回

5.泛型传递

baseresultentity<t>中的泛型t也就是我们所关心的回调数据,同样也是gson最后解析返回的数据,传递的过程根节点是通过定义service方法是给定的,例如:

public interface httppostservice {
  @post("appfiftytonegraph/videolink")
  call<retrofitentity> getallvedio(@body boolean once_no);
}

其中的retrofitentity就是用户关心的数据类,通过泛型传递给最后的接口。

6.强调

很多兄弟通过qq群反馈给我说,使用一个接口需要写一个对应的api类继承baseapi是不是很麻烦,我这里强调一下,这样封装是为了将一个api接口作为一个对象去封装,个人觉得有必要封装成一个类,在日后工程日益增加接口随着增加的同时,对象的做法更加有利于查找接口和修改接口有利于迭代。

操作类封装

1初始对象

首先初始化一个单利方便httpmanager请求;这里用了volatile的对象

  private volatile static httpmanager instance;

  //构造方法私有
  private httpmanager() {
  }

  //获取单例
  public static httpmanager getinstance() {
    if (instance == null) {
      synchronized (httpmanager.class) {
        if (instance == null) {
          instance = new httpmanager();
        }
      }
    }
    return instance;
  }

2接口处理和回调处理:

 /**
   * 处理http请求
   *
   * @param basepar 封装的请求数据
   */
  public void dohttpdeal(baseapi basepar) {
    //手动创建一个okhttpclient并设置超时时间缓存等设置
    okhttpclient.builder builder = new okhttpclient.builder();
    builder.connecttimeout(basepar.getconnectiontime(), timeunit.seconds);
    builder.addinterceptor(new cookieinterceptor(basepar.iscache()));

    /*创建retrofit对象*/
    retrofit retrofit = new retrofit.builder()
        .client(builder.build())
        .addconverterfactory(gsonconverterfactory.create())
        .addcalladapterfactory(rxjavacalladapterfactory.create())
        .baseurl(basepar.getbaseurl())
        .build();


    /*rx处理*/
    progresssubscriber subscriber = new progresssubscriber(basepar);
    observable observable = basepar.getobservable(retrofit)
        /*失败后的retry配置*/
        .retrywhen(new retrywhennetworkexception())
        /*生命周期管理*/
        .compose(basepar.getrxappcompatactivity().bindtolifecycle())
        /*http请求线程*/
        .subscribeon(schedulers.io())
        .unsubscribeon(schedulers.io())
        /*回调线程*/
        .observeon(androidschedulers.mainthread())
        /*结果判断*/
        .map(basepar);

    /*数据回调*/
    observable.subscribe(subscriber);
  }

首先通过api接口类baseapi的实现类中数据初始化okhttpclient和retrofit对象,其中包含了url,超时等,接着通过baseapi的抽象方法getobservable得到observable对象,得到observable对象以后,我们就能随意的切换现成来处理,整个请求通过compose设定的rxlifecycle来管理生命周期,所以不会溢出和泄露无需任何担心,最后再服务器数据返回时,通过map判断结果,剔除错误信息,成功以后返回到自定义的progresssubscriber对象中,所以接下来封装progresssubscriber对象。

progresssubscriber封装

progresssubscriber其实是继承于subscriber,封装的方法无非是对subscriber的回调方法的封装

  1. onstart():开始
  2. oncompleted():结束
  3. onerror(throwable e):错误
  4. onnext(t t):成功

1.请求加载框

http请求都伴随着加载框的使用,所以这里需要在onstart()使用前初始一个加载框,这里简单的用progressdialog代替

/**
 * 用于在http请求开始时,自动显示一个progressdialog
 * 在http请求结束是,关闭progressdialog
 * 调用者自己对请求数据进行处理
 * created by wzg on 2016/7/16.
 */
public class progresssubscriber<t> extends subscriber<t> {
  /*是否弹框*/
  private boolean showporgress = true;
  /* 软引用回调接口*/
  private softreference<httponnextlistener> msubscriberonnextlistener;
  /*软引用反正内存泄露*/
  private softreference<rxappcompatactivity> mactivity;
  /*加载框可自己定义*/
  private progressdialog pd;
  /*请求数据*/
  private baseapi api;


  /**
   * 构造
   *
   * @param api
   */
  public progresssubscriber(baseapi api) {
    this.api = api;
    this.msubscriberonnextlistener = api.getlistener();
    this.mactivity = new softreference<>(api.getrxappcompatactivity());
    setshowporgress(api.isshowprogress());
    if (api.isshowprogress()) {
      initprogressdialog(api.iscancel());
    }
  }


  /**
   * 初始化加载框
   */
  private void initprogressdialog(boolean cancel) {
    context context = mactivity.get();
    if (pd == null && context != null) {
      pd = new progressdialog(context);
      pd.setcancelable(cancel);
      if (cancel) {
        pd.setoncancellistener(new dialoginterface.oncancellistener() {
          @override
          public void oncancel(dialoginterface dialoginterface) {
            oncancelprogress();
          }
        });
      }
    }
  }


  /**
   * 显示加载框
   */
  private void showprogressdialog() {
    if (!isshowporgress()) return;
    context context = mactivity.get();
    if (pd == null || context == null) return;
    if (!pd.isshowing()) {
      pd.show();
    }
  }


  /**
   * 隐藏
   */
  private void dismissprogressdialog() {
    if (!isshowporgress()) return;
    if (pd != null && pd.isshowing()) {
      pd.dismiss();
    }
  }
}

由于progress的特殊性,需要指定content而且不能是application所以这里传递一个rxappcompatactivity,而同时上面的httpmanager同样需要,所以这里统一还是按照baseapi传递过来,使用软引用的方式避免泄露。剩下的无非是初始化,显示和关闭方法,可以详细看代码。

2.onstart()实现

在onstart()中需要调用加载框,然后这里还有网络缓存的逻辑,后面会单独讲解,现在先忽略它的存在。

 /**
   * 订阅开始时调用
   * 显示progressdialog
   */
  @override
  public void onstart() {
    showprogressdialog();
    /*缓存并且有网*/
    if (api.iscache() && apputil.isnetworkavailable(rxretrofitapp.getapplication())) {
       /*获取缓存数据*/
      cookieresulte cookieresulte = cookiedbutil.getinstance().querycookieby(api.geturl());
      if (cookieresulte != null) {
        long time = (system.currenttimemillis() - cookieresulte.gettime()) / 1000;
        if (time < api.getcookienetworktime()) {
          if (msubscriberonnextlistener.get() != null) {
            msubscriberonnextlistener.get().oncachenext(cookieresulte.getresulte());
          }
          oncompleted();
          unsubscribe();
        }
      }
    }
  }

3.oncompleted()实现

 /**
   * 完成,隐藏progressdialog
   */
  @override
  public void oncompleted() {
    dismissprogressdialog();
  }

4.onerror(throwable e)实现

在onerror(throwable e)是对错误信息的处理和缓存读取的处理,后续会讲解,先忽略。

/**
   * 对错误进行统一处理
   * 隐藏progressdialog
   *
   * @param e
   */
  @override
  public void onerror(throwable e) {
    dismissprogressdialog();
    /*需要緩存并且本地有缓存才返回*/
    if (api.iscache()) {
      observable.just(api.geturl()).subscribe(new subscriber<string>() {
        @override
        public void oncompleted() {

        }

        @override
        public void onerror(throwable e) {
          errordo(e);
        }

        @override
        public void onnext(string s) {
          /*获取缓存数据*/
          cookieresulte cookieresulte = cookiedbutil.getinstance().querycookieby(s);
          if (cookieresulte == null) {
            throw new httptimeexception("网络错误");
          }
          long time = (system.currenttimemillis() - cookieresulte.gettime()) / 1000;
          if (time < api.getcookienonetworktime()) {
            if (msubscriberonnextlistener.get() != null) {
              msubscriberonnextlistener.get().oncachenext(cookieresulte.getresulte());
            }
          } else {
            cookiedbutil.getinstance().deletecookie(cookieresulte);
            throw new httptimeexception("网络错误");
          }
        }
      });
    } else {
      errordo(e);
    }
  }

  /*错误统一处理*/
  private void errordo(throwable e) {
    context context = mactivity.get();
    if (context == null) return;
    if (e instanceof sockettimeoutexception) {
      toast.maketext(context, "网络中断,请检查您的网络状态", toast.length_short).show();
    } else if (e instanceof connectexception) {
      toast.maketext(context, "网络中断,请检查您的网络状态", toast.length_short).show();
    } else {
      toast.maketext(context, "错误" + e.getmessage(), toast.length_short).show();
    }
    if (msubscriberonnextlistener.get() != null) {
      msubscriberonnextlistener.get().onerror(e);
    }
  }

5.onnext(t t)实现

  /**
   * 将onnext方法中的返回结果交给activity或fragment自己处理
   *
   * @param t 创建subscriber时的泛型类型
   */
  @override
  public void onnext(t t) {
    if (msubscriberonnextlistener.get() != null) {
      msubscriberonnextlistener.get().onnext(t);
    }
  }

主要是是将得到的结果,通过自定义的接口返回给view界面,其中的软引用对象msubscriberonnextlistener是自定义的接口回调类httponnextlistener.

6.httponnextlistener封装

现在只需关心onnext(t t)和onerror(throwable e)接口即可,回调的触发点都是在上面的progresssubscriber中调用

/**
 * 成功回调处理
 * created by wzg on 2016/7/16.
 */
public abstract class httponnextlistener<t> {
  /**
   * 成功后回调方法
   * @param t
   */
  public abstract void onnext(t t);

  /**
   * 緩存回調結果
   * @param string
   */
  public void oncachenext(string string){

  }

  /**
   * 失败或者错误方法
   * 主动调用,更加灵活
   * @param e
   */
  public void onerror(throwable e){

  }

  /**
   * 取消回調
   */
  public void oncancel(){

  }
}

失败后的retry处理

这里你可能会问,retrofit有自带的retry处理呀,的确retrofit有自带的retry处理,但是有很多的局限,先看下使用

okhttpclient.builder builder = new okhttpclient.builder();
builder.retryonconnectionfailure(true);

使用起来还是很方便,只需要调用一个方法即可,但是它是不可控的,也就是没有办法设置retry时间次数,所以不太灵活,既然如此还不如自己封装一下,因为用rxjava实现这个简直小菜,无形中好像已经给rxjava打了广告,中毒太深。

很简单直接上代码:

 /**
 * retry条件
 * created by wzg on 2016/10/17.
 */
public class retrywhennetworkexception implements func1<observable<? extends throwable>, observable<?>> {
//  retry次数
  private int count = 3;
//  延迟
  private long delay = 3000;
//  叠加延迟
  private long increasedelay = 3000;

  public retrywhennetworkexception() {

  }

  public retrywhennetworkexception(int count, long delay) {
    this.count = count;
    this.delay = delay;
  }

  public retrywhennetworkexception(int count, long delay, long increasedelay) {
    this.count = count;
    this.delay = delay;
    this.increasedelay = increasedelay;
  }

  @override
  public observable<?> call(observable<? extends throwable> observable) {
    return observable
        .zipwith(observable.range(1, count + 1), new func2<throwable, integer, wrapper>() {
          @override
          public wrapper call(throwable throwable, integer integer) {
            return new wrapper(throwable, integer);
          }
        }).flatmap(new func1<wrapper, observable<?>>() {
          @override
          public observable<?> call(wrapper wrapper) {
            if ((wrapper.throwable instanceof connectexception
                || wrapper.throwable instanceof sockettimeoutexception
                || wrapper.throwable instanceof timeoutexception)
                && wrapper.index < count + 1) { //如果超出重试次数也抛出错误,否则默认是会进入oncompleted
              return observable.timer(delay + (wrapper.index - 1) * increasedelay, timeunit.milliseconds);

            }
            return observable.error(wrapper.throwable);
          }
        });
  }

  private class wrapper {
    private int index;
    private throwable throwable;

    public wrapper(throwable throwable, int index) {
      this.index = index;
      this.throwable = throwable;
    }
  }
}

使用

到这里,我们第一步封装已经完成了,下面讲解下如何使用,已经看明白的各位看官,估计早就看明白了使用方式,无非是创建一个api对象继承baseapi初始接口信息,然后调用httpmanager对象的dohttpdeal(baseapi basepar)方法,最后静静的等待回调类httponnextlistener<t>类返回的onnext(t t)成功数据或者onerror(throwable e)数据。

其实代码就是这样:

api接口对象

/**
 * 测试数据
 * created by wzg on 2016/7/16.
 */
public class subjectpostapi extends baseapi {
//  接口需要传入的参数 可自定义不同类型
  private boolean all;
  /*任何你先要传递的参数*/
//  string xxxxx;

  /**
   * 默认初始化需要给定回调和rx周期类
   * 可以额外设置请求设置加载框显示,回调等(可扩展)
   * @param listener
   * @param rxappcompatactivity
   */
  public subjectpostapi(httponnextlistener listener, rxappcompatactivity rxappcompatactivity) {
    super(listener,rxappcompatactivity);
    setshowprogress(true);
    setcancel(true);
    setcache(true);
    setmothed("appfiftytonegraph/videolink");
    setcookienetworktime(60);
    setcookienonetworktime(24*60*60);
  }

  public boolean isall() {
    return all;
  }

  public void setall(boolean all) {
    this.all = all;
  }

  @override
  public observable getobservable(retrofit retrofit) {
    httppostservice service = retrofit.create(httppostservice.class);
    return service.getallvediobys(isall());
  }
}

请求回调

 //  完美封装简化版
  private void simpledo() {
    subjectpostapi postentity = new subjectpostapi(simpleonnextlistener,this);
    postentity.setall(true);
    httpmanager manager = httpmanager.getinstance();
    manager.dohttpdeal(postentity);
  }

  //  回调一一对应
  httponnextlistener simpleonnextlistener = new httponnextlistener<list<subjectresulte>>() {
    @override
    public void onnext(list<subjectresulte> subjects) {
      tvmsg.settext("网络返回:\n" + subjects.tostring());
    }

    @override
    public void oncachenext(string cache) {
      /*缓存回调*/
      gson gson=new gson();
      java.lang.reflect.type type = new typetoken<baseresultentity<list<subjectresulte>>>() {}.gettype();
      baseresultentity resultentity= gson.fromjson(cache, type);
      tvmsg.settext("缓存返回:\n"+resultentity.getdata().tostring() );
    }

    /*用户主动调用,默认是不需要覆写该方法*/
    @override
    public void onerror(throwable e) {
      super.onerror(e);
      tvmsg.settext("失败:\n" + e.tostring());
    }

    /*用户主动调用,默认是不需要覆写该方法*/
    @override
    public void oncancel() {
      super.oncancel();
      tvmsg.settext("取消請求");
    }
  };

后续

到这里,封装功能中很多功能还没涉及和讲解,后续会陆续更新!

先给大家看看为师的完全体功能:

    1.retrofit+rxjava+okhttp基本使用方法
    2.统一处理请求数据格式
    3.统一的progressdialog和回调subscriber处理
    4.取消http请求
    5.预处理http请求
    6.返回数据的统一判断
    7.失败后的retry处理
    8.rxlifecycle管理生命周期,防止泄露
    9.文件上传下载(支持多文件,断点续传)
    10.cache数据持久化和数据库(greendao)两种缓存机制
    11.异常统一处理

来个图压压惊:

源码:

rxretrofit-终极封装-深入浅出&网络请求-github

其实我还有一个兄弟版本-传送门

我不会告诉你其实我还有个更加简单的版本

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网