秒懂Retrofit2之GsonConverter
版權申明】非商業目的可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/81387328
出自:shusheng007
系列文章
最簡單易懂的Retrofit2原始碼詳解
用Retrofit+RxJava2封裝優雅的網路請求框架
概述
前兩天分析了Retrofit的原始碼,個人認為其精髓就在於CallAdapter 與Converter的設計上,本文我們就先研究下Converter
的知識,下一篇再研究CallAdapter
。
Converter的作用
假設我們不為Retrofit
設定任何Converter
,那麼Retrofit
能正常工作嗎?有什麼限制?先看下面程式碼:
code1
@POST
@Multipart
Call<ResponseBody>method1(@Part("p") RequestBody rBody);
@POST
Call<Void>method2(@Body RequestBody rBody);
code2
@POST
@Multipart
Call<String>method1(@Part("p") Map<String,String> rBody);
@POST
Call<List<User>>method2(@Body User rBody);
code1 是沒有新增自定義converter
時可以做的,而code2是新增了GsonConverter
後可以做的。可以發現僅僅使用預設的converter
的話會在使用上存在巨大限制。
對於方法的請求引數來說
使用
@Part
,@PartMap
,@Body
標記的引數型別就只能是RequestBody
對於方法的返回結果來說
方法放回結果的泛型引數只支援
ResponseBody
與Void
那樣對我們的使用來說就麻煩了許多,需要不斷的將資料在我們自己的型別與ResponseBody
之間互相轉換。而GsonConverterFactory
就是為了將這個資料型別轉換的工作自動化而生的。
GsonConverterFactory原始碼解析
得益於Gson
的強大,使的 GsonConverterFactory
非常簡單,原始碼也僅僅只有3個類。
GsonConverterFactory
我就是通過這個工廠來呼叫請求轉換器requestBodyConverter
與結果轉換器responseBodyConverter
的
public final class GsonConverterFactory extends Converter.Factory {
//最常使用的靜態工廠方法,使用預設的Gson例項
public static GsonConverterFactory create() {
return create(new Gson());
}
//使用這個工廠方法可以從外部傳入Gson物件,我們可以對這個Gson物件做很多配置
public static GsonConverterFactory create(Gson gson) {
...
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
原始碼簡潔的令人髮指,首先由兩個靜態工廠方法可以獲得物件例項,其中一個可以出入一個Gson物件,這就產生了很多想象空間。因為我們可以在外部配置這個Gson
物件的各種屬性,關於如何配置,希望你調研一下,肯定又會驚歎於Gson
設計的精妙。剩下兩個函式我都不好意思講了,不然會有侮辱讀者智商的嫌疑。
GsonRequestBodyConverter
請求轉化器
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
結構很清晰,就是將一個T型別的資料value,例如為User
,通過convert()
轉化為RequestBody
型別的資料。如果你覺得看不懂,肯定不是看不懂邏輯而是看不懂轉換的程式碼,別裝了,承認看不懂不難!那就去研究Gson
吧,少年!
GsonResponseBodyConverter
結果轉換器
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
結構仍然很清晰,就是通過convert()
將RequestBody
型別的value資料轉換為我們期望的T型別的資料,例如T為User
。如果你又覺得看不懂,肯定不是看不懂邏輯而是看不懂轉換的程式碼,別裝了,承認看不懂不難!那就去研究Gson
吧,少女!
總結
目前除了GsonConverter
以外,原始碼中還包含了很多其他的的轉換器,例如jackson
、guave
、java8
、simplexml
等等,當遇到相應的場景時可以使用,如果現存的Converter
不能滿足我們的需求,我們就需要自己開發一個轉換器了。
相關文章
- 秒懂 this
- 秒懂Java反射Java反射
- 秒懂前端的快取策略前端快取
- 秒懂簡單工廠模式模式
- 一文秒懂!Python字串格式化之format方法詳解Python字串格式化ORM
- 秒懂負載均衡與反向代理負載
- 秒懂JVM的垃圾回收機制JVM
- 一張圖秒懂js盒模型JS模型
- 秒懂 Java 的三種代理模式Java模式
- 一文秒懂CPU使用率
- 一個示例,讓你秒懂SIPOC圖!
- Python和Java的區別?看完秒懂!PythonJava
- 一文秒懂分散式、叢集、負載均衡之間的區別分散式負載
- 【VMware】虛擬機器安裝Windows 10安裝教程(秒看秒懂)虛擬機Windows
- 秒懂系列,超詳細Java列舉教程!!!Java
- java求最小公倍數(親測秒懂)Java
- 三句話讀懂上海升級要點|秒懂上海升級
- Retrofit2分析
- Retrofit2<三> rxJava 分析RxJava
- 三分鐘秒懂BIO/NIO/AIO區別?AI
- 新手秒懂 - 高逼格解釋變數提升變數
- 【秒懂音視訊開發】12_播放WAV
- 數學公式難懂?動態圖片來解答,孩子看一遍秒懂公式
- 看完秒懂!Python就業前景及發展趨勢!Python就業
- 抽象類和介面到底是什麼垃圾——秒懂抽象
- 秒懂 Golang 中的 條件變數(sync.Cond)Golang變數
- 秒懂邊緣雲 | 邊緣雲技術進階
- 如何確定Kaizen的實施機會?看完秒懂AI
- 【秒懂音視訊開發】18_詳解YUV
- 【秒懂音視訊開發】14_AAC編碼
- Retrofit2原始碼解析(一)原始碼
- 一圖秒懂函式防抖和函式節流函式
- 秒懂雲通訊:號碼認證拍了拍你
- 秒懂雲通訊:通訊圈黑話大盤點
- 設計模式:抽象工廠模式,結合類圖秒懂!設計模式抽象
- 一文秒懂什麼是依賴注入, Ioc容器依賴注入
- 手寫自定義迭代器,秒懂迭代器底層原理
- 【秒懂音視訊開發】23_H.264編碼