Retrofit + OKHttp + RxJava 应用篇(获取wanandroid 服务器回传数据)
本文概述:
- 文章以Retrofit + OKHttp + RxJava 应用为主题,编写客户端软件,希望获取真实服务器(wanandroid 开放API)回传的数据;文章以真实案例,进一步深化了个人对于Rx 响应式编程思想的理解运用
软件架构:
编写思路:
- Retrofit控制OKHttp请求服务器(异步线程),将响应的结果拿给RxJava解析,结果在UI线程中(可进行更新Ui等操作)
编写思路:
- Retrofit控制OKHttp请求服务器(异步线程),将响应的结果拿给RxJava解析,结果在UI线程中(可进行更新Ui等操作)
具体案例:
业务需求:
- 借助 wanAndroid API作为真实服务器API,使用Retrofit+OKHttp+RxJava编写android客户端软件,实现获取服务器回传数据并打印至日志
前置准备:
-
wanAndroid API地址:www.wanandroid.com/blog/show/2
-
第一个API(总数据):www.wanandroid.com/project/tre…
-
第二个API (item数据):www.wanandroid.com/project/lis…
创建客户端API:
编写客户端 API接口:WangAndroidApi
-
处理接口中的注解参数:使用Retrofit中的 GET注解
-
总数据API地址:www.wanandroid.com/project/tre…
-
总数据对应注解参数:project/tree/json
- 域名可以认为是BaseUI,(www.wanandroid.com)这个是不变的
-
总数据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类
-
工程展示:代码较多,不予展示
-
第一种:使用在线转换工具
-
根据项目原始数据(www.wanandroid.com/project/tre…) 使用在线转换工具(www.bejson.com/json2javapo…) 生产 ProjectBean
-
网站使用截图:
-
- 第二种:在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函数会返回传入的类型
-
-
查询服务器回传的主数据:
-
此时Retrofit 已经拿到了服务器回传的数据
-
代码展示:
//这是一个耗时操作:那么就要给它分配异步线程 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的取值
-
细节二:甚至可以再次简化终点事件处理(Lamda 表达式 + Rx 编程事件自动推断)
-
但是这种写法可读性较差并不推荐
-
在此处是可以更新UI的,因为我现在已经切回了UI线程
-
-
-
此时基础功能编写完成:客户端已经可以拿到服务端回传的总数据了
-
-
查询服务器回传的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); }); } -
运行结果:
-
-
到现在为止:已经完成了从真实服务器拿到数据后,客户端进行解析,然后根据解析得到的数据进行进一步操作
- 案例搭建完毕