18.RxJava与Retrofit

一、RxJava
1,基本用法
创建 Observable、创建 Observer、 Subscribe
Observable一般用create(),也有just()、from()。
比如依次打印字符串数组 names 中的所有字符串:

String[] names = ...;
Observable.from(names)
    .subscribe(new Action1() {
        @Override
        public void call(String name) {
            Log.d(tag, name);
        }
    });

2.线程控制Scheduler
在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler。
Scheduler方法有immediate()、newThread()、io()、computation()。可以使用 subscribeOn()(发生线程) 和 observeOn() (运行线程)两个方法来对线程进行控制了。
比如:

Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
    .subscribe(new Action1() {
        @Override
        public void call(Integer number) {
            Log.d(tag, "number:" + number);
        }
    });

3.变换
将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
主要有map() 、flatMap()

二、Retrofit
1.定义API接口:

public interface PhoneService {
    @GET("/apistore/mobilenumber/mobilenumber")
    Call getResult(@Header("apikey") String apikey, @Query("phone") String phone);
}
private static final String BASE_URL = "http://apis.baidu.com";
private static final String API_KEY = "8e13586b86e4b7f3758ba3bd6c9c9135";
 
private void query(){
    //1.创建Retrofit对象
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())//解析方法
            .baseUrl(BASE_URL)//主机地址
            .build();
            
    //2.创建访问API的请求
    PhoneService service = retrofit.create(PhoneService.class);
    Call call = service.getResult(API_KEY, phoneView.getText().toString());
    
    //3.发送请求
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            //4.处理结果
            if (response.isSuccess()){
                PhoneResult result = response.body();
                if (result != null){
                    PhoneResult.RetDataEntity entity = result.getRetData();
                }
            }
        }
 
        @Override
        public void onFailure(Call call, Throwable t) {
 
        }
    });
}

3.结合RxJava

public interface Api {
    @GET
    Observable login(@Body LoginRequest request);

    @GET
    Observable register(@Body RegisterRequest request);
}
private static Retrofit create() {
            OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
            builder.readTimeout(10, TimeUnit.SECONDS);
            builder.connectTimeout(9, TimeUnit.SECONDS);

            if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                builder.addInterceptor(interceptor);
            }

            return new Retrofit.Builder().baseUrl(ENDPOINT)
                    .client(builder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
}
Api api = retrofit.create(Api.class);
        api.login(request)
              .subscribeOn(Schedulers.io())               //在IO线程进行网络请求
             .observeOn(AndroidSchedulers.mainThread())  //回到主线程去处理请求结果
            .subscribe(new Observer() {
                    @Override
                public void onSubscribe(Disposable d) {}

                @Override
                public void onNext(LoginResponse value) {}

                @Override
                public void onError(Throwable e) {
                    Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onComplete() {
                    Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show();
                }
            });

三、RxBinding
比如点击监听:

Button button = ...;
RxView.clickEvents(button) // 以 Observable 形式来反馈点击事件
    .subscribe(new Action1() {
        @Override
        public void call(ViewClickEvent event) {
            // Click handling
        }
    });

RxView.clickEvents(button)
    .throttleFirst(500, TimeUnit.MILLISECONDS)
    .subscribe(clickAction);
示例:RxJava + Retrofit + okHttp
一,Retrofit 写一个网络请求

以获取豆瓣 Top250 榜单为例,地址:https://api.douban.com/v2/movie/

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 实例,并且完成相关的配置

public static final String BASE_URL = "https://api.douban.com/v2/movie/";
Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl(BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create())
       .build();

说明:配置了接口的baseUrl和一个converter,GsonConverterFactory 是默认提供的Gson 转换器,Retrofit 也支持其他的一些转换器,详情请看官网Retrofit官网

3,创建一个 接口 ,代码如下:

public interface MovieService { 

 //获取豆瓣Top250 榜单 
 @GET("top250")
 Call getTop250(@Query("start") int start,@Query("count")int count);

}

说明:定义了一个方法getTop250,使用get请求方式,加上@GET 标签,标签后面是这个接口的 尾址top250,完整的地址应该是 baseUrl+尾址 ,参数 使用@Query标签,如果参数多的话可以用@QueryMap标签,接收一个Map

4,用Retrofit 创建 接口实例 MoiveService,并且调用接口中的方法进行网络请求,代码如下:

//获取接口实例
MovieService 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(); 
      } 
});

以上是异步方式请求,还有同步方式execute(),返回一个Response,代码如下:

Response response = call.execute();

以上就是用Retrofit 完成了一个网络请求,获取豆瓣top250 榜单电影。

以上示例是用get方式完成,如果要使用post 方式,我们只需要修改一下接口中的方法定义,如下:

public interface MovieService { 
        //获取豆瓣Top250 榜单 
       @FormUrlEncoded
       @POST("top250") 
       Call getTop250(@Field("start") int start, @Field("count") int count);
}

说明:使用POST 请求方式时,只需要更改方法定义的标签,用@POST 标签,参数标签用 @Field 或者@Body或者FieldMap,注意:使用POST 方式时注意2点,1,必须加上 @FormUrlEncoded标签,否则会抛异常。2,使用POST方式时,必须要有参数,否则会抛异常, 源码抛异常的地方如下:

if (isFormEncoded && !gotField) { 
      throw methodError("Form-encoded method must contain at least one @Field."); 
}

以上就是一个使用Retrofit 完成一个网络请求的完整示例,其他标签使用方式请看官网Retrofit官网,官网用法也介绍的比较详细,此外,发现了一篇博客也介绍得比较详细,Retrofit用法详解

二,配合RxJava 使用

1, 更改定义的接口,返回值不再是一个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())

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(); 
   } 
});

以上是加入RxJava 后的网络请求,返回不再是一个Call ,而是一个Observable, 在Activity / Fragment 中传入一个Subscriber 建立订阅关系,就可以在 onNext 中处理结果了,RxJava 的好处是帮我处理线程之间的切换,我们可以在指定订阅的在哪个线程,观察在哪个线程。我们可以通过操作符进行数据变换。整个过程都是链式的,简化逻辑。其中FlatMap 操作符 还可以解除多层嵌套的问题。总之,RxJava 很强大,能帮我处理很多复杂的场景,如果熟练使用的话,那么能提升我们的开发效率。这里不打算讲RxJava 的内容,如果还不了解RxJava ,或者还对RxJava不熟悉的话,推荐几篇写很优秀的博客。

1,RxJava 的经典文章,扔物线的 给 Android 开发者的 RxJava 详解

2,关于RxJava 友好的文章

3,关于RxJava 友好的文章-进阶

三,加入 OkHttp 配置

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

// 创建 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);//读操作超时时间 

  // 添加公共参数拦截器 
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();

以上只是配置了一些简单的项,如,连接超时时间,实际项目中,我们可能有一些公共的参数,如 ,设备信息,渠道,Token 之类的,每个接口都需要用,我们可以写一个拦截器,然后配置到OKHttpClient里,通过 builder.addInterceptor(basicParamsInterceptor) 添加,这样我们就不用每个接口都添加这些参数了。缓存也可以通过写一个拦截器来实现(后面文章再讲)。

以上就是Retrofit+RxJava+OkHttp实现网络请求的简单演示,如果每个接口都这么写的话,代码量太多,而且不优雅。所以还需要我们封装一下,由于篇幅有限,封装放到下一篇文章。

** Retrofit + RxJava + OkHttp 封装已更新,请看Retrofit + RxJava + OkHttp 让网络请求变的简单-封装篇**

参考博客:

1,Retrofit用法详解

2,基于Retrofit、OkHttp、Gson封装通用网络框架

3, RxJava 与 Retrofit 结合的最佳实践

作者:依然范特稀西
链接:https://www.jianshu.com/p/5bc866b9cbb9
來源:
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(18.RxJava与Retrofit)