当前位置: 移动技术网 > 移动技术>移动开发>Android > 【Android】Retrofit+RxJava+OkHttp的基础、封装和项目中的使用

【Android】Retrofit+RxJava+OkHttp的基础、封装和项目中的使用

2018年09月12日  | 移动技术网移动技术  | 我要评论

android】retrofit+rxjava+okhttp的基础、封装和项目中的使用。近些年很火的retrofit+rxjava+okhttp网络请求框架,功能强大,结构合理,使用简单方便。后面还会给大家发自己整理过的retrofit和rxjava、rxandroid和rxbus。希望大家点一下关注,让我这个懒癌患者有动力继续写下去!
本篇分三个部分:基础篇、封装篇和自己项目使用篇,项目是自己公司的app提取的,文章偏长可以分三部分一点点看,当初看了很多优秀的文章然后自己在整理写在印象笔记中,可惜当初没记下借鉴过的文章地址,十分抱歉。
github地址:https://github.com/bigeyechou/networkframe

简单介绍retrofit、okhttp和rxjava之间的关系:

retrofit:retrofit是square公司开发的一款针对android 网络请求的框架(底层默认是基于okhttp 实现)。 okhttp:也是square公司的一款开源的网络请求库。 rxjava :”a library for composing asynchronous and event-based programs using observable sequences for the java vm”(一个在 java vm 上使用可观测的序列来组成异步的、基于事件的程序的库)。rxjava使异步操作变得非常简单。

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

基础篇:

一、retrofit写一个网络请求:

1.引入retrofit的包,在build.gradle文件中添加如下配置:

compile 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit
compile 'com.google.code.gson:gson:2.6.2'//gson 库
//下面两个是rxjava 和 rxandroid
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//转换器,请求结果转换成model
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'//配合rxjava 使用

2.创建一个retrofit 实例,并且完成相关的配置:
配置了接口的 base_url 和一个 converter , gsonconverterfactory 是默认提供的 gson转换器。

public static final string base_url = "https://api.douban.com/v2/movie/";
retrofit retrofit = new retrofit.builder()
.baseurl(base_url)
.addconverterfactory(gsonconverterfactory.create())
.build();

3.创建一个接口:
定义了一个方法 gettop250 ,使用 get请求方式,加上@get 标签,标签后面是这个接口的 尾址top250,完整的地址应该是 baseurl+尾址 ,参数 使用@query标签,如果参数多的话可以用@querymap标 签,接收一个map。
使用 post 请求方式时,只需要更改方法定义的标签,用 @post 标签,参数标签用 @field 或者 @body 或者 fieldmap

public interface movieservice {
//获取豆瓣top250 榜单
@get("top250")
call gettop250 (@query("start") int start , @query("count") int count);

@formurlencoded
@post("top250")
call gettop250 (@field("start") int start , @field("count") int count);
}

使用 post 方式时需要注意两点:
- 必须加上 @formurlencoded标签,否则会抛异常。
- 必须要有参数,否则会抛异常, 抛异常的地方如下:

if (isformencoded && !gotfield) {
      throw methoderror("form-encoded method must contain at least one @field.");
}

4.用 retrofit 创建 接口实例 moiveservice 并且调用接口中的方法进行网络请求:
异步方式请求:

//获取接口实例
movieservice movieservice = retrofit.create(movieservice.class);
//调用方法得到一个call
call call = movieservice.gettop250(0,20);
 //进行网络请求
call.enqueue(new callback() {
       @override
       public void onresponse(call call, response response) {
            mmovieadapter.setmovies(response.body().subjects);     
            mmovieadapter.notifydatasetchanged();
       }
      @override
      public void onfailure(call call, throwable t) {
         t.printstacktrace();
      }
});

同步方式请求: 返回一个response

response response = call.execute();
二,配合rxjava 使用:
更改定义的接口,返回值不再是一个 call ,而是返回的一个 observble:
public interface movieservice {
//获取豆瓣top250 榜单
@get("top250")
observable gettop250(@query("start") int start, @query("count")int count);
}

2.创建 retrofit 的时候添加如下代码:

addcalladapterfactory(rxjavacalladapterfactory.create())

3.添加转换器converter(将 json 转为 javabean):

addconverterfactory(gsonconverterfactory.create())

举实际项目中使用的例子:

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

4.activity 或者 fragment 中传入 subscriber 建立订阅关系:

subscription subscription = movieservice.gettop250(0,20)
.subscribeon(schedulers.io())
.observeon(androidschedulers.mainthread())
.subscribe(new subscriber() {
@override
public void oncompleted() {

 }
@override
public void onerror(throwable e) {

}
@override
 public void onnext(moviesubject moviesubject) {
        mmovieadapter.setmovies(moviesubject.subjects);
        mmovieadapter.notifydatasetchanged();
   }
});

5.加入rxjava的好处:
- 加入 rxjava 后的网络请求,返回不再是一个 call ,而是一个 observable。
- 在activity / fragment 中传入一个subscriber 建立订阅关系,就可以在 onnext 中处理结果了。
- rxjava 的好处是帮我处理 线程之间的切换,我们可以在指定 订阅的在哪个线程,观察在哪个线程。
- 可以 通过操作符 进行数据变换。
- 整个过程都是链式的,简化逻辑。其中flatmap 操作符 还可以解除多层嵌套的问题。

rxjava 很强大,能帮我处理很多复杂的场景,如果熟练使用的话,那么能提升我们的开发效率。

三,加入 okhttp 配置:

通过okhttpclient 可以配置很多东西,比如 链接超时时间,缓存,拦截器 等等。代码如下:

okhttpclient.builder builder = new okhttpclient.builder();
     builder.connecttimeout(default_time_out, timeunit.seconds);//连接 超时时间
     builder.writetimeout(default_time_out,timeunit.seconds);//写操作 超时时间
     builder.readtimeout(default_time_out,timeunit.seconds);//读操作 超时时间
     builder.retryonconnectionfailure(true);//错误重连

// 添加公共参数拦截器
basicparamsinterceptor basicparamsinterceptor = new basicparamsinterceptor.builder()
    .addheaderparam("username","")//添加公共参数
    .addheaderparam("device","")
    .build();

builder.addinterceptor(basicparamsinterceptor);

// 创建retrofit
mretrofit = new retrofit.builder()
    .client(builder.build())
    .addcalladapterfactory(rxjavacalladapterfactory.create())
    .addconverterfactory(gsonconverterfactory.create())
    .baseurl(apiconfig.base_url)
    .build();

列举项目中用到的如下:

//项目中设置头信息
interceptor headerinterceptor = new interceptor() {
    @override
    public response intercept(chain chain) throws ioexception {
        request originalrequest = chain.request();
        request.builder requestbuilder = originalrequest.newbuilder()
                .addheader("accept-encoding", "gzip")
                .addheader("accept", "application/json")
                .addheader("content-type", "application/json; charset=utf-8")
                .method(originalrequest.method(), originalrequest.body());
        requestbuilder.addheader("authorization", "bearer " + baseconstant.token);//添加请求头信息,服务器进行token有效性验证
        request request = requestbuilder.build();
        return chain.proceed(request);
    }
};
okhttpbuilder.addinterceptor(headerinterceptor);

//项目中创建retrofit
retrofit = new retrofit.builder()
        .client(okhttpbuilder.build())
        .addconverterfactory(gsonconverterfactory.create())
        .addcalladapterfactory(rxjavacalladapterfactory.create())
        .baseurl(base_url)
        .build();
httpservice = retrofit.create(httpservice.class);

封装篇

一,创建一个 统一生成接口实例的管理类 retrofitservicemanager

创建了一个 retrofitservicemanager 类,该类采用 单例模式,在 私有的 构造方法中,生成了 retrofit 实例,并配置了okhttpclient 和一些 公共配置。
提供了一个create()方法,生成 接口实例,接收 class泛型。
代码如下:

public class retrofitservicemanager {
  private static final int default_time_out = 5;//超时时间 5s   
  private static final int default_read_time_out = 10;   
  private retrofit mretrofit;   

  private retrofitservicemanager(){ 
      // 创建 okhttpclient     
okhttpclient.builder builder = new okhttpclient.builder();     
builder.connecttimeout(default_time_out, timeunit.seconds);//连接超时时间       
builder.writetimeout(default_read_time_out,timeunit.seconds);//写操作 超时时间       
builder.readtimeout(default_read_time_out,timeunit.seconds);//读操作超时时间 

     // 添加公共参数拦截器       
     httpcommoninterceptor commoninterceptor = new httpcommoninterceptor.builder()
               .addheaderparams("paltform","android")
               .addheaderparams("usertoken","1234343434dfdfd3434")
               .addheaderparams("userid","123445")     
               .build();       
     builder.addinterceptor(commoninterceptor);  

     // 创建retrofit       
     mretrofit = new retrofit.builder()
               .client(builder.build()) 
               .addcalladapterfactory(rxjavacalladapterfactory.create())
               .addconverterfactory(gsonconverterfactory.create())
               .baseurl(apiconfig.base_url)   
               .build();   
 }

   private static class singletonholder{
        private static final retrofitservicemanager instance = new retrofitservicemanager();
    }

    /**
     * 获取retrofitservicemanager
     * @return
     */   
 public static retrofitservicemanager getinstance(){ 
      return singletonholder.instance;
   } 

  /**
    * 获取对应的service
    * @param service service 的 class     
    * @param    
    * @return 
    */ 
  public  t create(class service){
       return mretrofit.create(service);   
}

}

接口实例service都可以用这个来生成,代码如下:

mmovieservice = retrofitservicemanager.getinstance().create(movieservice.class);
二,创建接口,通过第一步获取实例

有了可以获取接口实例的方法,然后创建一个接口,代码如下:

public interface movieservice{ 
  //获取豆瓣top250 榜单 
  @get("top250")   
  observable gettop250(@query("start") int start, @query("count") int count); 

  @formurlencoded   
  @post("/x3/weather") 
  call getweather(@field("cityid") string cityid, @field("key") string key);
}
三,创建一个业务loader ,如xxxloder,获取observable并处理相关业务

创建 loader 的原因:每一个api 都写一个接口很麻烦,因此就把 请求逻辑 封装在 一个业务loader 里面,一个 loader 里面可以处理多个api 接口。代码如下:

public class movieloader extends objectloader {
  private movieservice mmovieservice;
  public movieloader(){ 
      mmovieservice = retrofitservicemanager.getinstance().create(movieservice.class);
    } 
  /**
    * 获取电影列表
    * @param start 
    * @param count   
    * @return   
    */ 
  public observable> getmovie(int start, int count){ 
      return observe(mmovieservice.gettop250(start , count)).map(new func1>() { 
        @override
        public list call(moviesubject moviesubject) { 
        return moviesubject.subjects;   
      } 
    });
  } 

public observable getweatherlist(string cityid,string key){   
      return observe(mmovieservice.getweather(cityid , key)).map(new func1() {   
       @override     
       public string call(string s) {
          //可以处理对应的逻辑后在返回
            return s;   
      }
    });
}

public interface movieservice{
    //获取豆瓣top250 榜单 
    @get("top250")     
    observable gettop250(@query("start") int start, @query("count")int count); 

    @formurlencoded 
    @post("/x3/weather")   
    call getweather(@field("cityid") string cityid, @field("key") string key); 
}
}
创建一个movieloader,构造方法中生成了mhttpservice,而 service 中可以定义和业务相关的多个api,比如:例子中的httpservice中,
可以定义和电影相关的多个api,获取电影列表、获取电影详情、搜索电影等api,就不用定义多个接口了。

movieloader 是从 objectloader 中继承下来的,objectloader 提取了一些公共的操作。代码如下:
/** 
 * 将一些重复的操作提出来,放到父类以免loader 里每个接口都有重复代码 
 */
public class objectloader { 
/**
  *
  * @param observable   
  * @param  
  * @return   
  */ 
protected   observable observe(observable observable){   
    return observable
      .subscribeon(schedulers.io())         
      .unsubscribeon(schedulers.io()) 
      .observeon(androidschedulers.mainthread()); 
  }
}
四,activity/fragment 中的调用

创建loader实例:

mmovieloader = new movieloader();

通过loader 调用方法获取结果,代码如下:

/**
 * 获取电影列表
 */
private void getmovielist(){
  mmovieloader.getmovie(0,10).subscribe(new action1>() { 
    @override 
    public void call(list movies) { 
        mmovieadapter.setmovies(movies);       
        mmovieadapter.notifydatasetchanged();     
        }
  }, new action1() {   
    @override     
    public void call(throwable throwable) {   
        log.e("tag","error message:"+throwable.getmessage());   
      } 
  });
}
五,统一处理结果和错误

1.统一处理请求结果:
现实项目中,所有接口的返回结果都是同一格式,如:

{
"status": 200,
"message": "成功",
"data": {}
}

在请求api 接口的时候,只关心想要的数据,也就上面的 data{ },其他的东西不太关心,请求失败 的时候可以根据 status 判断进行 错误处理。
包装返回结果:首先需要根据服务端定义的 json 结构创建一个 baseresponse 类,代码如下:

/**
 * 网络请求结果 基类 
 */
public class baseresponse { 
  public int status; 
  public string message;   
  public t data;   
  public boolean issuccess(){ 
    return status == 200; 
  }
}

有了统一的格式数据后,我们需要 剥离出data{ }返回给 上层调用者,创建一个 payload 类,代码如下:

/**
 * 剥离 最终数据
 */
public class payload implements func1{   
@override
  public t call(baseresponse tbaseresponse) {//获取数据失败时,包装一个fault 抛给上层处理错误
        if(!tbaseresponse.issuccess()){
          throw new fault(tbaseresponse.status,tbaseresponse.message); 
      }   
    return tbaseresponse.data; 
  }
}
<><>

payload 继承自 func1,接收一个baseresponse , 就是接口返回的 json 数据结构,返回的是 t,就是data{ },判断是否请求成功,请求成功 返回data,请求失败 包装成一个 fault 返回给上层统一处理错误。
在loader类里面获取结果后,通过map 操作符剥离数据。代码如下:

public observable> getmovie(int start, int count){
  return observe(mmovieservice.gettop250(start,count))       
    .map(new payload>());
}
<><><><>

2.统一处理错误:
在payload 类里面,请求失败时,抛出了一个fault 异常给上层,我在activity/fragment 中拿到这个异常,然后判断错误码,进行异常处理。在onerror () 中添加。
对应 错误码 处理 相应的错误,代码如下:

public void call(throwable throwable) { 
  log.e("tag","error message:"+throwable.getmessage()); 
  if(throwable instanceof fault){   
  fault fault = (fault) throwable;   
    if(fault.geterrorcode() == 404){   
      //错误处理
      }else if(fault.geterrorcode() == 500){ 
      //错误处理 
      }else if(fault.geterrorcode() == 501){     
      //错误处理 
    } 
  }
}
六,添加公共参数

实际项目中,每个接口都有一些基本的相同的参数,我们称之为公共参数,比如:userid、usertoken、username、deviceid等等,我们不必每个接口都去写,可以写一个拦截器,在拦截器里面拦截请求,为每个请求都添加相同的公共参数。
拦截器代码如下:

/*
 * 拦截器
 *
 * 向请求头里添加公共参数
 */
public class httpcommoninterceptor implements interceptor {   
private map mheaderparamsmap = new hashmap<>(); 
  public httpcommoninterceptor() { 
  }   
    @override
    public response intercept(chain chain) throws ioexception {   
    log.d("httpcommoninterceptor","add common params");   
        request oldrequest = chain.request();   
        // 添加新的参数,添加到url 中 
        /*httpurl.builder authorizedurlbuilder = oldrequest.url().newbuilder()     
        .scheme(oldrequest.url().scheme()) 
        .host(oldrequest.url().host());*/

      // 新的请求 
      request.builder requestbuilder =  oldrequest.newbuilder();
      requestbuilder.method(oldrequest.method(), oldrequest.body());

      //添加公共参数,添加到header中       
     if(mheaderparamsmap.size() > 0){     
          for(map.entry params:mheaderparamsmap.entryset()){ 
              requestbuilder.header(params.getkey(),params.getvalue());     
        }   
   }   
      request newrequest = requestbuilder.build(); 
      return chain.proceed(newrequest); 
  }  

  public static class builder{     
  httpcommoninterceptor mhttpcommoninterceptor;   
      public builder(){     
      mhttpcommoninterceptor = new httpcommoninterceptor();   
  }  

  public builder addheaderparams(string key, string value){     
      mhttpcommoninterceptor.mheaderparamsmap.put(key,value); 
      return this; 
  }    

  public builder  addheaderparams(string key, int value){ 
      return addheaderparams(key, string.valueof(value));
  }    

  public builder  addheaderparams(string key, float value){
      return addheaderparams(key, string.valueof(value)); 
  }

  public builder  addheaderparams(string key, long value){ 
      return addheaderparams(key, string.valueof(value));     
  }  

  public builder  addheaderparams(string key, double value){   
      return addheaderparams(key, string.valueof(value));   
  }

  public httpcommoninterceptor build(){
      return mhttpcommoninterceptor;   
  } 

  }
}

以上就是添加公共参数的拦截器,在 retrofitservicemanager 类里面加入okhttpclient 配置就好了。
代码如下:

// 添加公共参数拦截器
httpcommoninterceptor commoninterceptor = new httpcommoninterceptor.builder()   
      .addheaderparams("paltform","android") 
      .addheaderparams("usertoken","1234343434dfdfd3434")
      .addheaderparams("userid","123445")     
      .build();
builder.addinterceptor(commoninterceptor);

项目使用篇 —–>插入广告!本项目来源于金融研习社app,金融理财类的在线教育

项目是基于rxjava1
1.引入依赖:

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'com.squareup.okhttp3:logging-interceptor:3.5.0'

2.创建一个httpservice接口:

public interface httpservice {
/**
 * 获取用户详细资料
 */
@post("api/xxx/getuseralldetails")
observable getuseralldetails(@body getuseralldetailsrequestbean bean);

/**
 * @param apkurl 下载地址
 */
@get()
@streaming
call downloadnewapk(@url string apkurl);

/**
 * 获取推广大使分享图片
 */
@get("api/xxx/invitedimage")
observable getinvitedimage(@querymap map map);

}

3.创建http请求类,并在里面初始化并配置retrofit和okhttp:

public class httpmethods {
    public string tag = "httpmethods";
    public static final string cache_name = "xxx";
    public static string base_url = urlconstant.base_url;
    private static final int default_connect_timeout = 30;
    private static final int default_write_timeout = 30;
    private static final int default_read_timeout = 30;
    private retrofit retrofit;
    private httpservice httpservice;
    /**
     * 请求失败重连次数
     */
    private int retry_count = 0;
    private okhttpclient.builder okhttpbuilder;

    //构造方法私有
    private httpmethods() {
        //手动创建一个okhttpclient并设置超时时间
        okhttpbuilder = new okhttpclient.builder();

        /**
         * 设置缓存
         */
        file cachefile = new file(applicationcontext.context.getexternalcachedir(), cache_name);
        cache cache = new cache(cachefile, 1024 * 1024 * 50);
        interceptor cacheinterceptor = new interceptor() {
            @override
            public response intercept(chain chain) throws ioexception {
                request request = chain.request();
                if (!netutil.isnetworkconnected()) {
                    request = request.newbuilder()
                            .cachecontrol(cachecontrol.force_cache)
                            .build();
                }
                response response = chain.proceed(request);
                if (!netutil.isnetworkconnected()) {
                    int maxage = 0;
                    // 有网络时 设置缓存超时时间0个小时
                    response.newbuilder()
                            .header("cache-control", "public, max-age=" + maxage)
                            .removeheader(cache_name)// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
                            .build();
                } else {
                    // 无网络时,设置超时为4周
                    int maxstale = 60 * 60 * 24 * 28;
                    response.newbuilder()
                            .header("cache-control", "public, only-if-cached, max-stale=" + maxstale)
                            .removeheader(cache_name)
                            .build();
                }
                return response;
            }
        };
        okhttpbuilder.cache(cache).addinterceptor(cacheinterceptor);


        /**
         * 设置头信息
         */
        interceptor headerinterceptor = new interceptor() {
            @override
            public response intercept(chain chain) throws ioexception {
                request originalrequest = chain.request();
                request.builder requestbuilder = originalrequest.newbuilder()
                        .addheader("accept-encoding", "gzip")
                        .addheader("accept", "application/json")
                        .addheader("content-type", "application/json; charset=utf-8")
                        .method(originalrequest.method(), originalrequest.body());
                requestbuilder.addheader("authorization", "bearer " + baseconstant.token);//添加请求头信息,服务器进行token有效性验证
                request request = requestbuilder.build();
                return chain.proceed(request);
            }
        };
        okhttpbuilder.addinterceptor(headerinterceptor);


//        if (buildconfig.debug) {
        httplogginginterceptor logginginterceptor = new httplogginginterceptor(new httplogginginterceptor.logger() {
            @override
            public void log(string message) {
                logger.d(message);
            }


        });
        logginginterceptor.setlevel(httplogginginterceptor.level.body);
        //设置 debug log 模式
        okhttpbuilder.addinterceptor(logginginterceptor);
//        }
        /**
         * 设置超时和重新连接
         */
        okhttpbuilder.connecttimeout(default_connect_timeout, timeunit.seconds);
        okhttpbuilder.readtimeout(default_write_timeout, timeunit.seconds);
        okhttpbuilder.writetimeout(default_read_timeout, timeunit.seconds);
        //错误重连
        okhttpbuilder.retryonconnectionfailure(true);


        retrofit = new retrofit.builder()
                .client(okhttpbuilder.build())
                .addconverterfactory(gsonconverterfactory.create())//json转换成javabean
                .addcalladapterfactory(rxjavacalladapterfactory.create())
                .baseurl(base_url)
                .build();
        httpservice = retrofit.create(httpservice.class);
    }

    //在访问httpmethods时创建单例
    private static class singletonholder {
        private static final httpmethods instance = new httpmethods();

    }

    //获取单例
    public static httpmethods getinstance() {
        return singletonholder.instance;
    }

    /**
     * 获取retrofit
     */
    public retrofit getretrofit() {
        return retrofit;
    }

    public void changebaseurl(string baseurl) {
        retrofit = new retrofit.builder()
                .client(okhttpbuilder.build())
                .addconverterfactory(gsonconverterfactory.create())
                .addcalladapterfactory(rxjavacalladapterfactory.create())
                .baseurl(baseurl)
                .build();
        httpservice = retrofit.create(httpservice.class);
    }

    /**
     * 获取httpservice
     */
    public httpservice gethttpservice() {
        return httpservice;
    }

     /**
     * 设置订阅 和 所在的线程环境
     */
    public  void tosubscribe(observable o, subscriber s) {

        o.subscribeon(schedulers.io())
                .unsubscribeon(schedulers.io())
                .observeon(androidschedulers.mainthread())
                .retry(retry_count)//请求失败重连次数
                .subscribe(s);

    }
}

4.设置回调:
调用者自己对请求数据进行处理 成功时 通过result是否等于1分别回调onsuccees和onfault,默认处理了401错误转登录。

public class onsuccessandfaultsub extends subscriber implements progresscancellistener {
    /**
     * 是否需要显示默认loading
     */
    private boolean showprogress = true;
    private onsuccessandfaultlistener monsuccessandfaultlistener;

    private context context;
    private waitprogressdialog progressdialog;

    /**
     * @param monsuccessandfaultlistener 成功回调监听
     */
    public onsuccessandfaultsub(onsuccessandfaultlistener monsuccessandfaultlistener) {
        this.monsuccessandfaultlistener = monsuccessandfaultlistener;
    }

    /**
     * @param monsuccessandfaultlistener 成功回调监听
      * @param context                    上下文
      */
    public onsuccessandfaultsub(onsuccessandfaultlistener monsuccessandfaultlistener, context context) {
        this.monsuccessandfaultlistener = monsuccessandfaultlistener;
        this.context = context;
        progressdialog = new waitprogressdialog(context, this);
    }

    /**
     * @param monsuccessandfaultlistener 成功回调监听
      * @param context                    上下文
      * @param showprogress               是否需要显示默认loading
     */
    public onsuccessandfaultsub(onsuccessandfaultlistener monsuccessandfaultlistener, context context, boolean showprogress) {
        this.monsuccessandfaultlistener = monsuccessandfaultlistener;
        this.context = context;
        progressdialog = new waitprogressdialog(context, this);
        this.showprogress = showprogress;
    }

    private void showprogressdialog() {
        if (showprogress && null != progressdialog) {
            progressdialog.show();
        }
    }

    private void dismissprogressdialog() {
        if (showprogress && null != progressdialog) {
            progressdialog.dismiss();
        }
    }

    /**
     * 订阅开始时调用
      * 显示progressdialog
     */
    @override
    public void onstart() {
        showprogressdialog();
    }

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

    /**
     * 对错误进行统一处理
      * 隐藏progressdialog
     */
    @override
    public void onerror(throwable e) {
        try {

            if (e instanceof sockettimeoutexception) {//请求超时
            } else if (e instanceof connectexception) {//网络连接超时
                monsuccessandfaultlistener.onfault("网络连接超时");
            } else if (e instanceof sslhandshakeexception) {//安全证书异常
                monsuccessandfaultlistener.onfault("安全证书异常");
            } else if (e instanceof httpexception) {//请求的地址不存在
                int code = ((httpexception) e).code();
                if (code == 504) {
                    monsuccessandfaultlistener.onfault("网络异常,请检查您的网络状态");
                } else if (code == 404) {
                    monsuccessandfaultlistener.onfault("请求的地址不存在");
                } else {
                    monsuccessandfaultlistener.onfault("请求失败");
                }
            } else if (e instanceof unknownhostexception) {//域名解析失败
                monsuccessandfaultlistener.onfault("域名解析失败");
            } else {
                monsuccessandfaultlistener.onfault("error:" + e.getmessage());
            }
        } catch (exception e2) {
            e2.printstacktrace();
        } finally {
            log.e("onsuccessandfaultsub", "error:" + e.getmessage());
            dismissprogressdialog();
            progressdialog = null;

        }

    }

    /**
     * 当result等于1回调给调用者,否则自动显示错误信息,若错误信息为401跳转登录页面。
      */
    @override
    public void onnext(responsebody body) {
        try {
            final string result = compressutils.decompress(body.bytestream());
            log.e("body", result);
            jsonobject jsonobject = new jsonobject(result);
            int resultcode = jsonobject.getint("errorcode");
            if (resultcode == 1) {
                monsuccessandfaultlistener.onsuccess(result);
            } else {
                string errormsg = jsonobject.getstring("errormessage");
                monsuccessandfaultlistener.onfault(errormsg);
                log.e("onsuccessandfaultsub", "errormsg: " + errormsg);
            }
        } catch (exception e) {
            e.printstacktrace();
        }
    }

    /**
     * 取消progressdialog的时候,取消对observable的订阅,同时也取消了http请求
      */
    @override
    public void oncancelprogress() {
        if (!this.isunsubscribed()) {
            this.unsubscribe();
        }
    }
}
 *请求服务loading关闭监听 
 */
public interface progresscancellistener {
    void oncancelprogress();
}

5.请求的用法:
建议分类成不同的api,以便快速查找
api里面进行观察者和被观察者的订阅

private void getuserdata() {
    onsuccessandfaultlistener l = new onsuccessandfaultlistener() {
        @override
        public void onsuccess(string result) {//成功回调
            yxspreference.setuserdata(result);
            userdatabean = gsonutils.fromjson(result, userdetailresponsebean.class);
            fulldata();
        }

        @override
        public void onfault(string errormsg) {//失败的回调
            snackbarmanager.showshortmsg(getactivity(), errormsg);
        }
    };

    userapi.getuseralldetails(new onsuccessandfaultsub(l) , yxspreference.getmemberid()
    );
}

onsuccessandfaultsub 继承 subscriber

public class userapi {
    /**
     * 获取用户详细信息
     */
    public static void getuseralldetails(subscriber subscriber, int memberid) {
        getuseralldetailsrequestbean bean = new getuseralldetailsrequestbean();
        bean.getdata().setmemberid(memberid);
        observable observable = httpmethods.getinstance().gethttpservice().getuseralldetails(bean); //在httpserver中
        httpmethods.getinstance().tosubscribe(observable, subscriber);
    }
}
<><>

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网