RxJava 系列(二):Retrofit + OKHttp + RxJava 应用篇(获取wanandroid 服务器回传数据)

285 阅读5分钟

Retrofit + OKHttp + RxJava 应用篇(获取wanandroid 服务器回传数据)

本文概述:

  • 文章以Retrofit + OKHttp + RxJava 应用为主题,编写客户端软件,希望获取真实服务器(wanandroid 开放API)回传的数据;文章以真实案例,进一步深化了个人对于Rx 响应式编程思想的理解运用

软件架构:

图片.png

编写思路:

  • Retrofit控制OKHttp请求服务器(异步线程),将响应的结果拿给RxJava解析,结果在UI线程中(可进行更新Ui等操作)

编写思路:

  • Retrofit控制OKHttp请求服务器(异步线程),将响应的结果拿给RxJava解析,结果在UI线程中(可进行更新Ui等操作)

具体案例:

业务需求:

  • 借助 wanAndroid API作为真实服务器API,使用Retrofit+OKHttp+RxJava编写android客户端软件,实现获取服务器回传数据并打印至日志

前置准备:

创建客户端API:

图片.png

编写客户端 API接口:WangAndroidApi

  • 处理接口中的注解参数:使用Retrofit中的 GET注解

    • 总数据API地址:www.wanandroid.com/project/tre…

    • 总数据对应注解参数:project/tree/json

    • 总数据API对应注解:

       // 总数据
       @GET("project/tree/json")
       Observable<ProjectBean> getProject();  // 异步线程 耗时操作
      
    • item 数据API地址:www.wanandroid.com/project/lis…

    • item 数据对应注解参数:project/list/1/json?cid=294

    • item 数据对应注解:因为里面的 1 ,294均是变化的

      • 代码会自动将其补全
       //item数据
       @GET("project/list/{pageIndex}/json") // ?cid=294
       Observable<ProjectItem> getProjectItem(@Path("pageIndex") int pageIndex, @Query("cid") int cid);  // 异步线程 耗时操作
      
  • 补充:处理接口中的事件:根据对应的 JSON生成 JavaBean

    • 背景:服务器回传数据交给RxJava处理,那么起点应为Observable(被观察者)且在泛型中应当填写两 JSON数据各自对应的 JavaBean类
  • 客户端API接口完整代码:WangAndroidApi
 import com.xiangxue.rxjavademo.use.bean.ProjectBean;
 import com.xiangxue.rxjavademo.use.bean.ProjectItem;
 ​
 import io.reactivex.Observable;
 import retrofit2.http.GET;
 import retrofit2.http.Path;
 import retrofit2.http.Query;
 ​
 public interface WangAndroidApi {
 ​
     // 总数据
     @GET("project/tree/json")
     Observable<ProjectBean> getProject();  // 异步线程 耗时操作
 ​
     // ITem数据
     @GET("project/list/{pageIndex}/json") // ?cid=294
     Observable<ProjectItem> getProjectItem(@Path("pageIndex") int pageIndex, @Query("cid") int cid);  // 异步线程 耗时操作
 }

根据两组 JSON数据生成各自的 JavaBean类

  • 第二种:在androidStudio中安装格式转换插件(format)
  • 至此客户端API编写完毕
  • 编写Retrofit类(HttpUtil):管理客户端API的创建、调用、使用

     package com.xiangxue.rxjavademo.use.util;
     ​
     import com.facebook.stetho.okhttp3.StethoInterceptor;
     import com.google.gson.Gson;
     ​
     import java.util.concurrent.TimeUnit;
     ​
     import okhttp3.OkHttpClient;
     import okhttp3.logging.HttpLoggingInterceptor;
     import retrofit2.Retrofit;
     import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
     import retrofit2.converter.gson.GsonConverterFactory;
     ​
     public class HttpUtil {
     ​
         private static final String TAG = "HttpUtils";
     ​
         /**
          * 默认 test-a环境
          */
     ​
     //    定义BaseURL:这个东西是不变的
         public static String BASE_URL = "https://www.wanandroid.com/";
     ​
     //    BaseURL:也是可以自定义的
         public static void setBaseUrl(String baseUrl) {
             BASE_URL = baseUrl;
         }
     ​
         /**
          * Retrofit就两个功能:
          *     功能一:控制OKHttp请求服务器
          *     功能二:将服务器返回的数据交给RxJava处理
          *          RxJava只能用于处理回来的数据,不能拿这个去处理去的数据
          *              这个是由于Rx响应式编程的理念决定的
          * 根据各种配置创建出Retrofit
          *
          * @return 返回创建好的Retrofit
          */
         public static Retrofit getOnlineCookieRetrofit() {
             // OKHttp客户端
             OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
             // 各种参数配置:使用HTTPClient去链接的时候,也要设置这些参数
             OkHttpClient okHttpClient = httpBuilder
                     //配置
                     .addNetworkInterceptor(new StethoInterceptor())
                     //读取超时时间
                     .readTimeout(10000, TimeUnit.SECONDS)
                     //连接超时时间
                     .connectTimeout(10000, TimeUnit.SECONDS)
                     //写入超时时间
                     .writeTimeout(10000, TimeUnit.SECONDS)
                     .build();
     ​
     ​
             return new Retrofit.Builder().baseUrl(BASE_URL)
                     // TODO 请求用 OKhttp
                     //将OKHttp客户端丢给Retrofit(Retrofit不是网络请求框架,这个是一个很牛逼的封装框架,是做管理者的,不是干活的)
                     .client(okHttpClient)
     ​
                     // TODO 响应RxJava
                     // 添加一个json解析的工具:实现拿到 JSON数据后转成对应的 JavaBean
                     .addConverterFactory(GsonConverterFactory.create(new Gson()))
                     // 添加rxjava处理工具
                     .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
     ​
                     //Build设计模式
                     .build();
         }
     }
    

处理事件流向:RxJava解析服务器回传的数据

  • 推荐阅读:什么是响应式编程:以RxJava为例

  • 定义API

     //定义API
     private WangAndroidApi api;
    
  • 初始化API:使用泛型

     //API初始化:Retrofit初始化
     api = HttpUtil.getOnlineCookieRetrofit().create(WangAndroidApi.class);
    
    • create函数会返回传入的类型

      图片.png

  • 查询服务器回传的主数据:

    • 此时Retrofit 已经拿到了服务器回传的数据

      图片.png

    • 代码展示:

       //这是一个耗时操作:那么就要给它分配异步线程
       public void getProjectAction(View view) {
           // 获取网络API
           api.getProject()
               .subscribeOn(Schedulers.io()) // 上为面分配异步线程
               .observeOn(AndroidSchedulers.mainThread()) // 为下面分配主线程
               //使用简化版本的观察者Consumer(并不需要那么细致的事件处理函数)
               .subscribe(new Consumer<ProjectBean>() {
                   @Override
                   public void accept(ProjectBean projectBean) throws Exception {
                       Log.d(TAG, "accept: " + projectBean); // UI 可以做事情
                   }
               });
       }
      
      • 细节一:Schedulers的取值

        图片.png

      • 细节二:甚至可以再次简化终点事件处理(Lamda 表达式 + Rx 编程事件自动推断)

        • 但是这种写法可读性较差并不推荐

        • 在此处是可以更新UI的,因为我现在已经切回了UI线程

        图片.png

    • 此时基础功能编写完成:客户端已经可以拿到服务端回传的总数据了

      图片.png

  • 查询服务器回传的item数据:

    • 按道理是通过主数据id,查询对应的id

    • 先直接写死id:测试代码工作

       public void getProjectListAction(View view) {
           // 注意:这里的 294 是项目分类 所查询出来的数据
           // 上面的项目分类会查询出:"id": 294,"id": 402,"id": 367,"id": 323,"id": 314, ...
       ​
           // id 写死的
           api.getProjectItem(1, 294)
               // .....
               .subscribeOn(Schedulers.io()) // 上面 异步
               .observeOn(AndroidSchedulers.mainThread()) // 下面 主线程
               .subscribe(data->{
                   Log.d(TAG, "getProjectListAction: " + data);
               });
       ​
       }
      
    • 运行结果:

      图片.png

  • 到现在为止:已经完成了从真实服务器拿到数据后,客户端进行解析,然后根据解析得到的数据进行进一步操作

    • 案例搭建完毕