前言
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装
使用步骤
添加Retrofit库的依赖:
implementation 'com.google.code.gson:gson:2.8.0'(gson生成和解析库)
implementation 'com.squareup.okhttp3:okhttp:3.9.1'(开源的网络请求库)
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'(支持okhttp跟踪到一个网络请求的所有状态,包括请求头、请求体、响应行、 响应体,方便调试)
implementation 'com.squareup.retrofit2:retrofit:2.3.0'(实现将HTTP请求转换为Java接口)
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'(配合Rxjava 使用)
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'(转换器,请求结果转换成Model)
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.2.1'(一种帮助你做异步的框架. 类似于 AsyncTask. 但其灵活性和扩展性远远强于前者. 从能力上讲, 如果说 AsycnTask 是 DOS 操作系统, RxJava 是 Window 操作系统。)
网络请求的大概分为四部分,retrofit主要负责封装网络请求,okhttp负责完成网络请求,logging-interceptor负责网络请求和响应的输出日志方便调试,rxjava一种帮助你做异步的框架,gson负责json的生成和解析,将请求结果转为相应的Model;
1.Retrofit是什么?
Retrofit将您的HTTP API转换为Java接口;Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装;
2.Retrofit如何使用?
public static final ApiService service = new Retrofit.Builder()
.baseUrl("http://www.baidu.com")
.build()
.create(ApiService.class);
2.1创建HTTP请求的API接口
1)通过Retrofit.Builder内部类创建Retrofit实例,需要调用baseUrl(url)指定请求的跟路径和调用build()方法执行Retrofit实例创建,在build()方法内部会创建Retrofit需要的其他默认参数;
注意:下面三种方式设置URL都可以,但是推荐第三种方式设置,当把url传入给Retrofit对URL进行解析,HttpUrl会解析请求的协议(http和https,或者其他协议),域名,端口等信息,实际上HttpUrl会为域名后面加上“/”;
"http://www.baidu.com/?key=value"
"http://www.baidu.com"
"http://www.baidu.com/" //推荐格式
最终请求的时候跟路径会处理为"http://www.baidu.com/"格式;
http://www.baidu.com/?c=api&a=getList&p=1&model=1&page_id=0&create_time=0&client=android&version=1.3.0&time=1584694243&device_id=000000000000000&show_sdv=1
2)调用Retrofit类create()创建接口ApiService实例
创建接口ApiService实例时借助Java提供Proxy动态代理类实现ApiService代理和实例的创建;
public interface ApiService {
@GET("group/{id}/users")
Call<ResponseBody> groupList(@Path("id") int groupId);
}
2.2请求执行
//请求回调在UI线程执行
apiService.groupList(23)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
3.注解详情
3.1请求方法注解
既然涉及HTTP的请求接口,则需要涉及HTTP请求的方法;
请求方法 类 备注说明
GET retrofit2.http.GET
POST retrofit2.http.POST
PATCH retrofit2.http.PATCH
HEAD retrofit2.http.HEAD
DELETE retrofit2.http.DELETE
OPTIONS retrofit2.http.OPTIONS
HTTP的请求方法,请求路径是baseurl和GET等方法指定相对路径组成一个完整路径;通过@Path方法可以动态设置路径中指定参数{id};@Url可以动态替换相对路径,同时也可以@Path方法可以动态设置路径中指定参数{id};
HTTP retrofit2.http.HTTP
HTTP请求可以指定以上所有请求方法,同时也可以@Path方法可以动态设置路径中指定参数{id};
@GET("group/{id}/users")
Observable<String> groupList(@Path("id") int groupId);
@HTTP(method = "GET", path = "group/{id}/users",hasBody = false)
Observable<String> groupList(@Path("id") int groupId);
//通过Url动态设置相对路径,请求方法不设置相对路径,@Url指定的动态url参数做为第一个参数
@GET()
Observable<String> groupList(@Url String url, @Path("id") int groupId);
4.GSON和Converter
//converters 被添加的顺序将是它们被Retrofit尝试的顺序
public static final ApiService service = new Retrofit.Builder()
.baseUrl("http://www.baidu.com")
.client(HttpUtils.client)
.addConverterFactory(StringConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(EntityUtils.gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
// .callbackExecutor()
// .callFactory()
// .validateEagerly()
.build()
.create(ApiService.class);
默认Retrofit支持ResponseBody响应体,调用API方法返回Call<ResponseBody>;
Call<T>定义的是范型,在实际开发中我们希望ResponseBody直接转换为我们需要类型方便开发;
@GET("group/{id}/users")
Call<Result.Data<List<Item>>> groupList(@Path("id") int groupId);
1)如何实现这种效果,这时就需要借助Gson转换器,现引入gson和转换gson库;
implementation 'com.google.code.gson:gson:2.8.0'(gson生成和解析库)
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'(转换器,请求结果转换成Model)
2)创建Gson转换器
创建Gson对象
public final class EntityUtils {
private EntityUtils() {}
public static final Gson gson = new GsonBuilder()
.registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter())
.create();
}
添加Gson转换器
Retrofit.addConverterFactory(GsonConverterFactory.create(EntityUtils.gson))
这样就可以实现ResponseBody和Gson转换;
Call<Result.Data<List<Item>>>data = apiService.groupList(23)
5.RxJava和CallAdapter
引入RxJava类库:
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'(配合Rxjava 使用)
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.2.1'(一种帮助你做异步的框架. 类似于 AsyncTask. 但其灵活性和扩展性远远强于前者.
从能力上讲, 如果说 AsycnTask 是 DOS 操作系统, RxJava 是 Window 操作系统。)
(4.GSON和Converter)这一章节主要说明Call<T>中T返回的替换,CallAdapter主要实现Call替换;用Observable替换Call,Observable基于订阅模式实现;
1)添加CallAdapter
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
2)定义API接口:
/**
* <p>分类列表</p>
* @param c
* @param a
* @param page
* @param model(0:首页,1:文字,2:声音,3:影像,4:单向历)
* @param pageId
* @param time
* @param deviceId
* @param show_sdv
* @return
*/
// @GET("/")
@HTTP(method = "get", path = "/",hasBody = false)
Observable<Result.Data<List<Item>>> getList(@Query("c") String c, @Query("a") String a, @Query("p") int page, @Query("model") int model, @Query("page_id") String pageId, @Query("create_time") String createTime, @Query("client") String client, @Query("version") String version, @Query("time") long time, @Query("device_id") String deviceId, @Query("show_sdv") int show_sdv);
3)调用API接口
apiService.getList("api","getList",page,model,pageId,createTime,"android","1.3.0", TimeUtil.getCurrentSeconds(), deviceId,1)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Result.Data<List<Item>>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
view.showOnFailure();
}
@Override
public void onNext(Result.Data<List<Item>> listData) {
int size = listData.getDatas().size();
if(size>0){
view.updateListUI(listData.getDatas());
}else {
view.showNoMore();
}
}
});
像上面的这种情况最后我们无法获取到返回的Header和响应码的,如果我们需要这两者,提供两种方案:
1、用Observable<Response<T>> 代替 Observable<T> ,这里的Response指retrofit2.Response
2、用Observable<Result<T>> 代替 Observable<T>,这里的Result是指retrofit2.adapter.rxjava.Result,这个Result中包含了Response的实例