国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - Retrofit 源碼分析初探

Retrofit 源碼分析初探

2022-02-19 16:37低情商的大仙 Android

這篇文章主要介紹了Retrofit 源碼分析初探,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

現如今,Android開發中,網絡層Retrofit+Okhttp組合好像已成標配,身為技術人員,這么火的框架當然得一探究竟,不為裝逼,純粹是為了充電而已。

基本使用介紹

介紹源碼前,我們先看下Retrofit的基本使用,大致了解下流程,跟著這個流程來分析源碼才不會亂。

1、初始化Retrofit對象

?
1
2
3
4
5
Retrofit retrofit = new Retrofit.Builder()
    //使用自定義的mGsonConverterFactory
    .addConverterFactory(GsonConverterFactory.create())
    .baseUrl("http://apis.baidu.com/txapi/")
    .build();

2、定義接口

?
1
2
3
4
5
public interface APi {
 
  @GET("hello/world")
  Call<News> getNews(@Query("num") String num,@Query("page")String page);
}

3、發起網絡請求

?
1
2
3
4
5
6
7
8
9
10
11
12
13
mApi = retrofit.create(APi.class);
Call<News> news = mApi.getNews("1", "10");
news.enqueue(new Callback<News>() {
  @Override
  public void onResponse(Call<News> call, Response<News> response) {
 
  }
 
  @Override
  public void onFailure(Call<News> call, Throwable t) {
 
  }
});

Retrofit本質分析

看到上面的整個流程,不去探究源碼的話肯定一臉懵逼,我就定義了一個接口,指定了下返回值,為毛這個接口就可以直接用了?接口的實現呢?我隨便寫一個返回值,不指定返回Call行不行?待著這些疑問,我們大致也可以猜出Retrofit是干什么的了。

猜測:Retrofit主要就是為我們定義的接口創造了一個實例,然后這個實例調用接口中的方法將我們定義在注解中的值拼裝成發起http請求所要的信息,最后利用這些信息產生一個我們在接口返回值中規定的對象,這個對象可以用來發起真正的請求。
簡單的講,Retrofit就是把注解中的東西拼成http請求的對象,然后由這個對象去發起請求。

驗證猜測

是誰實現了這個接口

發起網絡請求時,有這樣一句:

?
1
mApi = retrofit.create(APi.class);

很明顯,接口的實現應該是這個create干的事,我們跟進去看看源碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public <T> T create(final Class<T> service) {
 Utils.validateServiceInterface(service);
 if (validateEagerly) {
  eagerlyValidateMethods(service);
 }
 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
   new InvocationHandler() {
    private final Platform platform = Platform.get();
 
    @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
      throws Throwable {
     // If the method is a method from Object then defer to normal invocation.
     if (method.getDeclaringClass() == Object.class) {
      return method.invoke(this, args);
     }
     if (platform.isDefaultMethod(method)) {
      return platform.invokeDefaultMethod(method, service, proxy, args);
     }
     ServiceMethod<Object, Object> serviceMethod =
       (ServiceMethod<Object, Object>) loadServiceMethod(method);
     OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
     return serviceMethod.adapt(okHttpCall);
    }
   });
}

這里我們不用去看一些細節,只去關注我們想知道的,這個Create方法到底干了什么,看到Proxy.newProxyInstance,哦!這就很明顯了,這里接口之所以能夠直接調用是使用了動態代理技術,產生了一個代理對象。binggo,一個問題解決!!!

什么時候開始將注解中參數拼裝成http請求的信息的?

動態代理是干什么的?(大家最好單獨去學習下Java的動態代理,有時候非常有用,資料網上大把大把的)
使用動態代理一般是為了攔截方法,好在個方法執行的時候,在執行之前或之后干些自己的事情。這里回顧下Retrofit的使用,通過Create方法產生代理對象后直接就調用定義的方法了。那么,所有的小動作必然是在調用接口方法的時候干的。具體就是invoke中的方法

?
1
2
3
4
5
6
7
8
9
10
if (method.getDeclaringClass() == Object.class) {
 return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
 return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
  (ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);

前兩個if判斷主要是為了跳過object和object中內置的一些方法,除了這些,剩下的所有方法必然是我們在接口中定義的,也就是我們要攔截的。那么真正干事的就是三句:

?
1
2
3
4
ServiceMethod<Object, Object> serviceMethod =
        (ServiceMethod<Object, Object>) loadServiceMethod(method);
      OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
      return serviceMethod.adapt(okHttpCall);

其中loadServiceMethod()方法就是用來拼裝http請求信息的,這個問題解決!

如何產生發起http請求對象的?

經過上面的分析, OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);這就很明顯就是用來生產這個對象的。

如何將對象轉換成我們在接口中指定的返回值的?

這里要說明下,之前我們定義接口的時候是這樣的:

?
1
2
@GET("hello/world")
  Call<News> getNews(@Query("num") String num,@Query("page")String page);

這里的Call和Okhttp的Call其實很像,其實連方法都幾乎一樣,但是Retrofit和Rxjava一起用的時候又可以這樣定義

?
1
2
3
4
@GET("book/search")
  Observable<Book> getSearchBook(@Query("q") String name,
                  @Query("tag") String tag, @Query("start") int start,
                  @Query("count") int count);

這里指定的返回值不再是Call,而是變成了RxJava的Observable,所以這里肯定有一步轉換,能將之前拼裝的信息轉換成我們指定的對象,具體核心就是最后一行的serviceMethod.adapt()干的。

總結

經過以上分析,我們對Retrofit大致是干什么的很清楚了,主要就是拼裝http信息,并轉換成我們要的能夠發起http請求的對象。本文只是一個初探,后面我們將對每一步進行深入分析。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/35edc0f0ab45

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 992人人草 | 中文字幕亚洲一区二区三区 | 美日韩免费视频 | 亚洲毛片在线观看 | 另类视频网站 | 午夜色电影 | 国产精品美女久久久久久久久久久 | 中文字幕一区二区三区乱码图片 | 999精品| 中文字幕久久久 | 久久av网站 | 自拍视频网 | 四虎免费紧急入口观看 | 在线观看免费视频黄 | 日韩欧美中文字幕在线视频 | 亚洲专区国产精品 | 欧美日韩中文字幕 | 国产韩国精品一区二区三区 | 激情五月婷婷综合 | 欧美一区二区三区久久精品 | 欧美极品一区二区 | 国产高清一级片 | 亚洲在线 | 午夜视频免费在线观看 | 曰本人一级毛片免费完整视频 | 亚洲精品区 | 偷拍呻吟高潮91 | 亚洲视频欧美视频 | 国产欧美一区二区精品性色 | 自拍偷拍专区 | 久久久xxx| 91在线看片| 久久久精品呻吟 | 综合自拍 | 国产一区| 99久久影院 | 懂色av一区二区三区 | 免费在线观看黄色 | 亚洲精品视频在线 | 亚洲一区二区福利 | 龙珠z普通话国语版在线观看 |