在接到服务器响应后,目前无论是OKhttp还是Retrofit都只能接收到String字符串类型的数据,在实际开发中,通常需要对字符串进行解析将其转变为一个Java Bean对象。
Retrofit提供了多个转换器使得响应能够自动完成数据的转换。
json解析:
添加依赖
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
使用“玩安卓”的开放API
定义接口
定义接口
package com.dingjiaxiong.myretrofit;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface WanAndroidService {
@POST("user/login")
@FormUrlEncoded
Call<ResponseBody> login(@Field("username") String username,@Field("password") String pwd);
}
编写测试
package com.dingjiaxiong.myretrofit;
import org.junit.Test;
import java.io.IOException;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.Retrofit;
public class WanAndroidUnitTest {
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.wanandroid.com/").build();
WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
@Test
public void loginTest() throws IOException {
Response<ResponseBody> response = wanAndroidService.login("dingjiaxiong", "200039").execute();
System.out.println(response.body().string());
}
}
运行
现在想把这一段字符串转成一个Java Bean对象
导入Gson库依赖
implementation 'com.google.code.gson:gson:2.8.6'
使用这个工具
https://www.bejson.com/
查看一下返回数据的格式
使用网站工具 → Json生成java类
修改类名和包名
直接复制到项目中
将response转换为对象
可以看到生成成功了,给类加上打印方法
再次运行
成功
以上都是 自己【手动】完成的反序列化。
接下来直接使用转换器完成
复制一个接口文件
将类型直接设置成Java Bean
并在测试中添加转换器
Retrofit retrofi2 = new Retrofit.Builder().baseUrl("https://www.wanandroid.com/")
.addConverterFactory(GsonConverterFactory.create()) // 添加转换器
.build();
WanAndroidService2 wanAndroidService2 = retrofit.create(WanAndroidService2.class);
@Test
public void loginConvertTest() throws IOException {
Call<BaseResponse> call = wanAndroidService2.login("dingjiaxiong", "200039");
Response<BaseResponse> response = call.execute();
BaseResponse baseResponse = response.body();
System.out.println(baseResponse);
}
运行
报错了,啊这,看下代码
这儿写错了
OK,再次运行
和手动转换结果一致。
在实际开发中,可能会存在:需要先请求A接口,再请求B接口的情况,比如需要请求获取收藏列表文章,但是需要先登录拿到Cookie才能请求收藏文章列表接口。
此时请求就有了先后顺序。
这样会使得代码很冗长
Retrofit的接口方法的返回类型必须是Call,如果能够将Call改为RxJava中的Observable,对于嵌套的情况,就能得到非常方便、优雅的解决。
→ 这就是适配器。
添加依赖
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
同步
修改接口
登录接口
@POST("user/login")
@FormUrlEncoded
Flowable<BaseResponse> login2(@Field("username") String username, @Field("password") String pwd);
获取文章列表接口
@GET("lg/collect/list/{pageNum}/json")
Flowable<ResponseBody> getArticle(@Path("pageNum") int pageNum);
↓
使用适配器
Map<String,List<Cookie>> cookies = new HashMap<>();
Retrofit retrofit3 = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
.callFactory(new OkHttpClient.Builder()
.cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> list) {
cookies.put(url.host(),list);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = WanAndroidUnitTest.this.cookies.get(url.host());
return cookies == null ? new ArrayList<>() : cookies;
}
})
.build())
.addConverterFactory(GsonConverterFactory.create()) // 添加转换器
//添加适配器
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
WanAndroidService2 wanAndroidService3 = retrofit3.create(WanAndroidService2.class);
@Test
public void rxjavaTest(){
wanAndroidService3.login2("dingjiaxiong","200039")
.flatMap(new Function<BaseResponse, Publisher<ResponseBody>>() {
@Override
public Publisher<ResponseBody> apply(BaseResponse baseResponse) throws Throwable {
return wanAndroidService3.getArticle(0);
}
})
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.newThread())
.subscribe(new Consumer<ResponseBody>() {
@Override
public void accept(ResponseBody responseBody) throws Throwable {
System.out.println(responseBody.string());
}
});
while (true){}
}
成功根据cookie拿到结果。