Retrofit與okhttp都是Square公司出品浸颓,retrofit就是在okhttp的基礎(chǔ)上做了一層封裝耕赘。網(wǎng)絡(luò)請求相關(guān)操作交給Okhttp處理搪哪,我們只需要通過簡單的配置就能使用retrofit來進行網(wǎng)絡(luò)請求了巡扇。
Retrofit使用入門
首先創(chuàng)建一個接口:
public interface UserService {
@GET("users/{user}/lessons")
Call<List<Lesson>> listLessons(@Path("user") String user);
}
這個接口是為了通過一個url獲取用戶課程列表的接口,當然看著這個url地址好像也不是一個完整的能夠使用的url地址炊琉,確實是這樣的展蒂,Retrofit請求的地址是由兩部分組成的,一部分是后面要介紹的Retrofit對象中的baseUrl和類似上面接口中的path地址共同構(gòu)成的苔咪。
接下來我們是不是要定義一個實現(xiàn)該接口的類呢 ? 當然不是的啦锰悼。我們接下來要做的是只需構(gòu)造一個Retrofit對象即可,至于原理团赏,后面會說到箕般。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.test.com/")
.build();
UserService service = retrofit.create(UserService.class);
Call<List<Lesson>> lessonCall = service.listLessons("test");
Response<List<Lesson>> result = null;
//同步調(diào)用
result = lessonCall.execute();
//異步調(diào)用
lessonCall.enqueue(new Callback<List<Lesson>>() {
@Override
public void onResponse(Call<List<Lesson>> call, Response<List<Lesson>> response) {
result = response.body();
}
@Override
public void onFailure(Call<List<Lesson>> call, Throwable t) {
t.printStackTrace();
}
});
這樣就能輕易的調(diào)用http請求了,當然了舔清,這只是一個小小的簡單的demo丝里,Retrofit的功能不止這些。
Retrofit使用更上一層樓
前面我們弄了一個很基本的一個例子体谒,下面我們將更進一步使用Retrofit更多的功能杯聚。
請求類型: 我們都知道http的請求類型有GET
,POST
,DELETE
,PUT
,HEAD
,PATCH
這些類型,而與之相對應(yīng)的抒痒,Retrofit也包含了相對應(yīng)的注解給予支持幌绍,@GET
,@POST
,@DELETE
,@PUT
,@HEAD
,@PATCH
使用對應(yīng)的注解即可。
請求參數(shù):
-
@Query && @QueryMap
:@Query
用于http請求的單個query參數(shù)傳遞;@QueryMap
用于多個參數(shù)傳遞评汰,鍵值對纷捞。 -
@Field && @FieldMap
:@Field
用于post請求的單個參數(shù)傳遞;@FieldMap
用于post請求多個參數(shù)傳遞痢虹。 -
@Header && @HeaderMap
:@Header
用于單個請求頭參數(shù);@HeaderMap
用于多個請求頭參數(shù)傳遞被去。 -
@Part && @PartMap
:@Part
用于單個文件的上傳;@PartMap
用于多個文件上傳。 -
@Path
:用于path路徑變量的傳遞接收奖唯。
上述示例代碼:
@GET("users/{user}/lessons")
Call<List<Lesson>> listLessons(@Path("user") String user);
@GET("users/getuser")
Call<User> getUser(@Query("userId")String userId);
@GET("users/getUserByCondition")
Call<List<User>> getUserByCondition(@QueryMap Map<String,String> conditionMap);
@POST("users/authorization")
Call<User> authorization(@HeaderMap Map headerMap);
@Multipart//當有文件需要上傳時加入
@POST("users/add")
Call<User> addUser(@FieldMap Map userInfo, @Part("photo")MultipartBody.Part file);
上面這些示例都是可以直接返回對應(yīng)的結(jié)果類型惨缆,但如果我們想做一個通用的Retrofit封裝的http請求工具類,那就只好返回最原始的string類型丰捷,畢竟不同請求返回結(jié)果類型不同坯墨,像這樣:
public interface CommonHttpService{
@GET
Call<String> getHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap);
@FormUrlEncoded
@POST
Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @FieldMap Map<String,String> formMap);
@POST
Call<String> postHttpRequest(@Url String url, @HeaderMap Map<String,String> headerMap, @QueryMap Map<String,String> queryMap, @Body String body);
}
你會發(fā)現(xiàn)與前面的有些許不同,首先呢病往,@POST
或@GET
后面沒有跟上一部分path路徑了捣染,而是改由參數(shù)中的@Url String url
在調(diào)用方法時傳入,增加了靈活性停巷。
Converter
如果僅僅是這樣是返回不了對應(yīng)的結(jié)果類型的耍攘,需要用到converter榕栏,converter的作用就是將RequestBody或ResponseBody轉(zhuǎn)換為我們需要的類型,例如前面的我們想要使請求返回String類型還需要加上依賴:
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-scalars</artifactId>
<version>LATEST</version>
</dependency>
然后在構(gòu)造Retrofit對象時蕾各,加上ScalarsConverterFactory
的配置:
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com")
.addConverterFactory(ScalarsConverterFactory.create())
.build();
ScalarsConverterFactory
里面包含了對ResponseBody進行String扒磁,原始數(shù)據(jù)類型及其包裝類的轉(zhuǎn)換。
目前式曲,Retrofit已經(jīng)有了幾個官方的converter:
//uses Gson for serialization to and from JSON
Gson: com.squareup.retrofit2:converter-gson
//uses Jackson for serialization to and from JSON
Jackson: com.squareup.retrofit2:converter-jackson
//uses Moshi for serialization to and from JSON
Moshi: com.squareup.retrofit2:converter-moshi
//A Converter which uses Protocol Buffer binary serialization
Protobuf: com.squareup.retrofit2:converter-protobuf
//A Converter which uses Wire for protocol buffer-compatible serialization.
Wire: com.squareup.retrofit2:converter-wire
//A Converter which uses Simple for XML serialization.
Simple XML: com.squareup.retrofit2:converter-simplexml
//A Converter which supports converting strings and both primitives and their boxed types to text/plain bodies.
Scalars : com.squareup.retrofit2:converter-scalars
這些converter已經(jīng)能基本滿足我們?nèi)粘5男枰朔镣校彩掠欣猓热缥覀円用芙饷芰咝撸膶懡Y(jié)果等兰伤,所以這時候就需要我們自己來寫converter.我們以自定義一個 String Converter作為一個例子:
-
自定義converter:
先定義一個converter factory:
public class CustomStringConverterFactory extends Converter.Factory {
public static CustomStringConverterFactory create() {
return new CustomStringConverterFactory();
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
if (type == String.class) {
return new CustomStringConverter();
}
return null;
}
}
這里我們只是將ResponseBody進行轉(zhuǎn)換,如果你同時要將RequestBody進行轉(zhuǎn)換脆贵,那就同時要覆寫public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit)
方法.
定義Converter,轉(zhuǎn)換的邏輯在這里面進行:
public class CustomStringConverter implements Converter<ResponseBody, String> {
@Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
}
最后一步就是將converterfactory加入到Retrofit對象構(gòu)造中使用:
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.test.com") .addConverterFactory(CustomStringConverterFactory.create())
.build();
好了医清,這樣就能愉快的使用你自己定義的converter了,這里需要注意的是你如果添加的converter有多個的話小心順序。