Retrofit2學習番外——自定義Converter與CallAdapter
在自己擼了一遍自定義Converter與CallAdapter之後,終於有了一點了解,即使是侷限與使用階段。(另外本次的Demo參考了Retrofit2 探索)
原始碼地址:https://github.com/374901588/Retrofit2Demo.git
(注意:用於演示的Demo就是簡單的把請求的結果set到TextView上了,沒有做其他處理了)
用於測試的資料格式如下:
Contributor.java
為自定義的對應於上述資料的實體類,其中只包含login、id、contributions
三個屬性。
1、首先是自定義Converter,我在這裡模仿實現了GsonConverter
的功能,即在Demo中將Call<ResponseBody>
轉換為Call<List<Contributor>>
。主要程式碼如下:
private static class CustomConverter implements Converter<ResponseBody,List<Contributor>> {
public static final CustomConverter INSTANCE=new CustomConverter();
@Override
public List<Contributor> convert(ResponseBody value) throws IOException {
List<Contributor> list=new Gson().fromJson(value.string(),new TypeToken<List<Contributor>>(){}.getType());
return list;
}
}
public static class CustomConverterFactory extends Converter.Factory {
public static final CustomConverterFactory INSTANCE = new CustomConverterFactory();
public static CustomConverterFactory create() {
return INSTANCE;
}
// 我們只關心從ResponseBody 到 List<Contributor>> 的轉換,所以其它方法可不覆蓋
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
//不能直接用type==new TypeToken<List<Contributor>>(){}.getType()),將會得到false
//因為==是用於判斷兩個引用變數是否相等,但是這裡的==右邊是new的一個新的,所以肯定是“不==”的
Log.d("測試---》",""+(type==new TypeToken<List<Contributor>>(){}.getType()));
if (type.equals(new TypeToken<List<Contributor>>(){}.getType())) {
return CustomConverter.INSTANCE;
}
//其它型別我們不處理,返回null就行
return null;
}
}
2、接著是實現自定義的CallAdapter,這裡是模仿實現RxJavaCallAdapter
的功能,即在Demo中將Call<List<Contributor>>
轉換為Observable<List<Contributor>>
。主要程式碼如下:
public static class CustomCallAdapter implements CallAdapter<List<Contributor>,Observable<List<Contributor>>> {
private final Type responseType;
CustomCallAdapter(Type type) {
responseType=type;
}
@Override
public Type responseType() {
return responseType;
}
@Override
public Observable<List<Contributor>> adapt(Call<List<Contributor>> call) {
Log.d("測試-----5","responseType="+responseType);
try {
List<Contributor> contributorList=call.execute().body();
return Observable.just(contributorList);
} catch (IOException e) {
Log.e("異常",e.getMessage());
}
return null;
}
}
public static class CustomCallAdapterFactory extends CallAdapter.Factory {
public static final CustomCallAdapterFactory INSTANCE=new CustomCallAdapterFactory();
/**
* returnType為需要轉換的目標型別(原始型別),比如在本例中,需要轉換為Observable<List<Contributor>>,所以returnType就為其原始型別,即Observable.class對應的型別
*/
@Override
public CallAdapter<?,?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType=getRawType(returnType);//提取returnType的原始類型別,例如,表示List <?擴充套件Runnable>返回List.class
//因此在對比的時候我們只要rawType==Observable.class,而不是與new TypeToken<Observable<List<Contributor>>>(){}.getType()對比
if (rawType==Observable.class&&returnType instanceof ParameterizedType) {
Type callReturnType=getParameterUpperBound(0,(ParameterizedType)returnType);
return new CustomCallAdapter(callReturnType);
}
return null;
}
}
由於本人能力有限,不能模仿得像原本的那麼厲害,且迫於時間緊張,無心去分析原始碼,所以這裡只是簡易的實現功能。且需要注意執行contributors3()
方法時需要在子執行緒中,因為在CustomCallAdapter
的adapt()
方法中有執行call.execute()
,這會用於網路請求,如果執行contributors3()
方法時需要不在子執行緒中就會出現android.os.NetworkOnMainThreadException
。
相關文章
- Retrofit2之CallAdapter和ConverterAPT
- Cordova學習--iOS自定義外掛iOS
- 【django學習-24】自定義外掛Django
- 學習筆記|AS入門(番外) 技能篇筆記
- Vue學習(二)自定義指令Vue
- Angular學習(4)自定義指令Angular
- 自定義註解初步學習
- mybatis 自定義外掛MyBatis
- vue自定義全域性元件(或自定義外掛)Vue元件
- gradle自定義外掛Gradle
- WM自定義桌面"今日外掛"
- es 自定義分詞外掛分詞
- apisix~自定義外掛的部署API
- iOS學習筆記--PresentedVC自定義彈窗iOS筆記
- element-ui - 原始碼學習 - 自定義事件UI原始碼事件
- 學習JUC原始碼(2)——自定義同步元件原始碼元件
- C學習--自定義字串連線函式字串函式
- webService學習(二)—— 呼叫自定義物件引數Web物件
- Java學習筆記之自定義異常Java筆記
- 自定義View相關學習(一) (SlantedTextView ,canvas)TextViewCanvas
- [番外]-練習MySQL沒素材?來一波字串操作MySql字串
- spring boot學習(5): 程式exit code自定義Spring Boot
- 強化學習實戰 | 自定義Gym環境強化學習
- 有關自定義View的學習知識點View
- 步步學習自定義View:Hencoder 精簡版學習筆記(一)View筆記
- 自定義Gradle-Plugin 外掛GradlePlugin
- Kube-Scheduler外掛的自定義
- jQuery如何製作自定義外掛jQuery
- Gradle自定義外掛詳解Gradle
- gulp進階-自定義gulp外掛
- Gradle理論與實踐四:自定義Gradle外掛Gradle
- 淺析MyBatis(三):聊一聊MyBatis的實用外掛與自定義外掛MyBatis
- svelte元件:Svelte3自定義Navbar+Tabbr元件|svelte自定義外掛元件
- Python學習之如何引用Python自定義模組?Python
- 安卓學習筆記31:使用自定義檢視繪製文字、圖形與影像安卓筆記
- gradle自定義任務和外掛Gradle
- APISIX Ingress 如何支援自定義外掛API
- 自定義jquery外掛簡單介紹jQuery