Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 網絡框架 Retrofit2.0介紹、使用和封裝

Android 網絡框架 Retrofit2.0介紹、使用和封裝

編輯:關於Android編程

前言

時至今日,Android的網絡框架不再像之前那麼到處都是,隨著Google把 HttpClient直接刪掉,似乎意味著Android越來越成熟。網絡框架中的佼佼者Volley也不再那麼光鮮,取而代之的是 Retrofit 和 okHttp。
感覺很像 OnePiece 中白胡子的離去象征著時代的變革,新時代的開始,多弗的垮台象征著七武海制度的取締一樣,不會使用Retrofit + okHttp + RxJava等一系列技術,就邁不進新時代的門檻,也不足以稱為一個合格的開發者。

哈哈閒話不多說了,只是在 Android這個平台上 開發這麼長時間的一點感觸。各位看看笑笑也就算了。還是來介紹 Retrofit 吧。(直接略過1.9)

本文的所有代碼在 retrofitLearn;

1. Retrofit介紹

A type-safe HTTP client for Android and Java
一個用於Android和Java平台的類型安全的網絡框架

Retrofit is a type-safe REST client for Android built by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
Retrofit 是一個Square開發的類型安全的REST安卓客戶端請求庫。這個庫為網絡認證、API請求以及用OkHttp發送網絡請求提供了強大的框架 。

Retrofit 把REST API返回的數據轉化為Java對象,就像ORM框架那樣,把數據庫內的存儲的數據轉化為相應的Java bean對象。

那麼我們知道Retrofit是一個類型安全的網絡框架,而且它是使用REST API的,接下來我們看看什麼是REST吧。

2. REST 介紹:

Resources Representational State Transfer
資源表現層狀態轉化

每一個URI代表一種資源 客戶端和服務器之間,傳遞這種資源的某種 表現層(“資源”具體呈現出來的形式,比如.txt,.png,.jpg) 客戶端通過四個HTTP動詞(GET用來獲取資源,POST用來新建或更新資源,PUT用來更新資源,DELETE用來刪除資源)對服務器端資源進行操作,實現”表現層狀態轉化”

關於REST,這裡只僅僅列出了結論,文末有超級好的鏈接,請查看。如果你所使用的API是REST的,那麼恭喜你,這樣的API看起來真的很舒服,慶幸的是我司就使用的是REST API。

知道了REST是什麼,那接下啦就開始介紹Retrofit的用法啦。

3. Retrofit基本用法(未封裝)

1.在build.gradle中添加依賴

//okHttp
compile 'com.squareup.okhttp3:okhttp:3.2.0'

//retrofit
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'

2.創建接口,聲明API

//Retrofit turns your HTTP API into a Java interface.
//創建接口,聲明GitHub的API
public interface GitHubAPI {

     /*
       請求該接口:https://api.github.com/users/baiiu
     */
     @GET("users/{user}") 
     Call userInfo(@Path("user") String user);
}

3.在MainActivity.onCreate()方法中調用

/*
1.初始化OkHttpClient
*/
OkHttpClient client = new OkHttpClient();

/*
2.創建Retrofit
*/
retrofit = new Retrofit.Builder()
        //設置OKHttpClient
        .client(client)
        //設置baseUrl,注意,baseUrl必須後綴"/"
        .baseUrl("https://api.github.com/")

        //添加Gson轉換器
        .addConverterFactory(GsonConverterFactory.create())
        .build();

/*
2.獲取GitHub的API
*/
GitHubAPI gitHubAPI = retrofit.create(GitHubAPI.class);

/*
3.異步調用
*/
Call userCall = gitHubAPI.userInfo("baiiu");
userCall.enqueue(new Callback() {
      @Override public void onResponse(Call call, Response response) {
        User body = response.body();
        LogUtil.d(body == null ? "body == null" : body.toString());
      }

      @Override public void onFailure(Call call, Throwable t) {
        /*
         判斷是否被cancel掉了
        */
        if (call.isCanceled()) {
          LogUtil.d("the call is canceled , " + toString());
        } else {
          LogUtil.e(t.toString());
        }
      }
    });

/*
取消調用
*/
//userCall.cancel();

/*
同步調用,舉個例子,寫法如下(當然不能在主線程調用):
*/


//Each instance can only be used once, but calling clone() will create a new instance that can be used.
Call clone = userCall.clone();

Response response = clone.execute();
User body = response.body();
LogUtil.d(body == null ? "body == null" : body.toString());

注意:
1. 設置BaseUrl時必須後綴”/”,如 https://api.github.com/,這篇文章說的超清晰:Retrofit 2.0: The biggest update yet on the best HTTP Client Library for Android

2. 因為Retrofit在創建時候傳入了BaseUrl,所以基本上所有請求都基於該BaseUrl了。但是總有些API不是以該BaseUrl開頭的,特別是有些公司可能不是restful API的。那麼該怎麼辦呢。Retrofit提供了一個注解@Url解決這個問題,可以在運行時直接使用該Url直接訪問。代碼如下:

//使用@Url注解,傳入該Url地址就OK啦,跨過BaseUrl,直接訪問該Url地址
@GET Call getNewsList(@Url String url);

恩,接下來,知道了Retrofit的基本使用,接下來就是介紹Retrofit的注解了。

4. Retrofit注解

Retrofit使用注解來聲明API的請求方式、請求參數等。這裡只介紹一下它的 @Header 注解,其他的請閱讀 官網文檔 和 鴻洋的 Retrofit2 完全解析 探索與okhttp之間的關系。(這塊寫了也是翻譯官方文檔的和參考鴻樣的,會拉長篇幅)

請求頭的設置可以通過 @Header 注解添加,又有兩種添加方式:

設置靜態的請求頭。
@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call> widgetList();

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call getUser(@Path("username") String username);
動態的設置請求頭。
@GET("user")
Call getUser(@Header("Authorization") String authorization)

Note that headers do not overwrite each other. All headers with the same name will be included in the request.
同一個請求的同一個請求頭在不同地方的設置不會被覆蓋,而是會被全部添加進請求頭中。

Headers that need to be added to every request can be specified using an OkHttp interceptor.
如果要給每個請求都添加同樣的Header時,可以使用okHttp的 Interceptor

那麼,接下來就介紹Interceptor。

5.Interceptors使用

Retrofit 2.0 底層強制依賴okHttp,所以可以使用okHttp的攔截器Interceptors 來對所有請求進行再處理。

Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.

使用時,實現 Interceptor 接口,做我們自己的處理。
目前使用中,一般用來設置UA設置緩存策略打印Log 等。這裡介紹一個設置UA的Interceptor:

1.創建設置UA的Interceptor

public final class UserAgentInterceptor implements Interceptor {
  private static final String USER_AGENT_HEADER_NAME = "User-Agent";
  private final String userAgentHeaderValue;

  public UserAgentInterceptor(String userAgentHeaderValue) {
    this.userAgentHeaderValue = userAgentHeaderValue;
  }

  @Override public Response intercept(Chain chain) throws IOException {
    final Request originalRequest = chain.request();

    final Request requestWithUserAgent = originalRequest.newBuilder()

        //移除先前默認的UA
        .removeHeader(USER_AGENT_HEADER_NAME)

        //設置UA
        .addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)


        .build();
    return chain.proceed(requestWithUserAgent);
  }
}

2.創建okHttpClient時 設置該Interceptor

okHttpClient = new OkHttpClient.Builder()
        //添加UA
        .addInterceptor(new UserAgentInterceptor(HttpHelper.getUserAgent()))

        //失敗重連
        .retryOnConnectionFailure(true)

        //time out
        .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
        .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)

        .build();

Interceptors 和 Header 的配合使用讓我們很方便的使用Http本身的緩存。之前用Volley的時候這塊就比較難處理。解下來就說說Retrofit的緩存機制。

封裝的代碼在GitHub上:retrofitLearn;

6. 配置網絡緩存

使用Retrofit 感覺最方便的就是它提供的緩存方式(雖然這是Http本身的),我們可以隨便通過Header和Interceptor配置自己的緩存策略。

6.1 緩存設置原理:

緩存的設置是通過設置 Http請求頭和響應頭中的 Cache-Controlmax-age 屬性達到的。在復寫 Interceptor 時,通過設置響應頭的 Cache-Control 來達到目的。關於Http的本身的緩存命中請查看文末鏈接 (畢竟Http也是個大家伙) 。

6.2 緩存設置步驟

設置緩存目錄
retrofit本身默認無緩存,連緩存目錄都沒有提供默認的,所以 要想實現緩存,必須要在創建OkHttpClient時設置緩存目錄。 這塊超級坑,自己試了半天,最終看了下Cache那邊的源碼,竟然沒有默認的緩存目錄!!!

設置緩存的方式

通過添加 @Headers("Cache-Control: max-age=120") 進行設置。添加了Cache-Control 的請求,retrofit 會默認緩存該請求的返回數據。 通過Interceptors實現緩存。

6.3 實現Interceptor進行緩存

提供了兩種緩存策略(參考),設置緩存時Application Interceptor 和 Net Interceptor 都要設置:

AllCachedInterceptor
有網沒網都先走緩存,可以設置間歇時間。
同時可以針對某一個request設置單獨的緩存時間,使用 @Headers("Cache-Control: max-age=120") 就行。

OnOffLineCachedInterceptor
有網可以不走緩存,可設定時間,設置為0意味著有網不走緩存,全部刷新數據;無網強制讀取緩存數據。

到現在為止,關於Retrofit的基本用法和緩存設置已經了解了,寫點例子就已經會用了,接下來肯定就是進行封裝了,讓它更便於調用。

7. Retrofit 封裝

封裝Retrofit是為了提供更方便的調用,更好的配置和使用。那麼看到開頭的Retrofit調用方式,大概有這麼幾個步驟:
1. 創建OkHttpClient
2. 創建Retrofit實例
3. 獲取我們寫的API interface
4. 在代碼中異步調用

那麼封裝時候也肯定從這幾步入手:

7.1 初始化OkHttpClient

創建OkHttpFactory類,初始化OkHttpClient並對外提供該實例的單例。並提供一個 HttpHelper 類用於提供所需要的參數,比如UA。
這樣做的好處是,程序中會使用OkHttp做一些其他請求操作,比如下載、上傳等網絡操作,就可用共用一個OkHttpClient。

這裡使用枚舉生成單例。

enum OKHttpFactory {

  INSTANCE;

  private final OkHttpClient okHttpClient;

  private static final int TIMEOUT_READ = 25;
  private static final int TIMEOUT_CONNECTION = 25;

  OKHttpFactory() {
    //打印請求Log
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

    //緩存目錄
    Cache cache = new Cache(MyApplication.mContext.getCacheDir(), 10 * 1024 * 1024);

    okHttpClient = new OkHttpClient.Builder()
        //打印請求log
        .addInterceptor(interceptor)

        //stetho,可以在chrome中查看請求
        .addNetworkInterceptor(new StethoInterceptor())

        //添加UA
        .addInterceptor(new UserAgentInterceptor(HttpHelper.getUserAgent()))

        //必須是設置Cache目錄
        .cache(cache)

        //走緩存,兩個都要設置
        .addInterceptor(new OnOffLineCachedInterceptor())
        .addNetworkInterceptor(new OnOffLineCachedInterceptor())

        //失敗重連
        .retryOnConnectionFailure(true)

        //time out
        .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
        .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)

        .build();
  }

  public OkHttpClient getOkHttpClient() {
    return okHttpClient;
  }
}

7.2 初始化Retrofit

依然使用枚舉創建單例:

public enum RetrofitClient implements ApiContants {
  INSTANCE;

  private final Retrofit retrofit;

  RetrofitClient() {
    retrofit = new Retrofit.Builder()
        //設置OKHttpClient
        .client(OKHttpFactory.INSTANCE.getOkHttpClient())

        //baseUrl
        .baseUrl(GITHUB_BASEURL)

        //gson轉化器
        .addConverterFactory(GsonConverterFactory.create())

        .build();
  }

  public Retrofit getRetrofit() {
    return retrofit;
  }
}

7.3 創建ApiFactory類封裝所有API

如題,創建ApiFactory類管理所有的API interface,對外提供方法獲取他們,這樣調用時會方便很多,而且也便於修改。

public enum ApiFactory {
  INSTANCE;

  private final GitHubAPI gitHubAPI;
  private final AnotherAPI anotherAPI;

  ApiFactory() {
    gitHubAPI = RetrofitClient.INSTANCE.getRetrofit().create(GitHubAPI.class);
    anotherAPI = RetrofitClient.INSTANCE.getRetrofit().create(AnotherAPI.class);
  }

  public GitHubAPI gitHubAPI() {
    return gitHubAPI;
  }

  public AnotherAPI getAnotherAPI() {
    return anotherAPI;
  }
}

這樣封裝在外部調用時會方便很多,比如:

    Call userCall = ApiFactory.gitHubAPI().userInfo("baiiu");

這樣封裝自己覺得還不錯,就可以開心的寫代碼啦。接下來說說一個神奇的工具。

8. Stetho 一個神奇的工具

首先:使用該工具需要翻牆。 不能翻牆的還是使用Charles吧。

gradle中添加:
  compile 'com.facebook.stetho:stetho:1.3.1'
  compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
打開chrome,輸入chrome://inspect
點擊你的程序進行inspect,就可以直接使用Chrome進行抓包、調試你的應用啦。但是不能翻牆的話,你會看到一片空白。。。

結語:

畢竟Retrofit出來已經很久了,沒有的趕緊用用吧。在使用Retrofit時,深深趕緊到其對Http本身機制的應用之深,真的感覺到非常棒的應用體驗。用Retrofit作為網絡框架,簡直就能感覺到它設計之美,更何況還能和RxJava結合起來,美到不行。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved