1. 程式人生 > >【Android實戰】----從Retrofit原始碼分析到Java網路程式設計以及HTTP權威指南想到的

【Android實戰】----從Retrofit原始碼分析到Java網路程式設計以及HTTP權威指南想到的

一、簡介

        接上一篇【Android實戰】----基於Retrofit實現多圖片/檔案、圖文上傳 中曾說非常想搞明白為什麼Retrofit那麼屌。最近也看了一些其原始碼分析的文章以及親自查看了原始碼,發現其對Java網路程式設計及HTTP權威指南有了一個很好的詮釋。一直以來,都信奉一個原則,在這個新技術日新月異的時代,如何在Java界立足,憑藉的就兩點:

        1、基本功,包括:Java基本知識,(Java程式設計思想、Effective Java),Java進階(Java虛擬機器、Java設計模式)、網路相關(這個時代沒有網路就沒有一切,Java網路程式設計、HTTP權威指南、TCP/IP協議),計算機系統相關(編譯原理、深入理解計算機系統等)這些都是根本,所謂萬變不離其宗,在掌握這些基本功的基礎上,再學習新技術,面對日新月異的新技術時就會遊刃有餘。

        2、將瑣碎知識串聯起來的能力,也就是歸納總結能力。無論是在工作中還是學習中,起初用到的知識是東一塊、西一塊,其實許多東西都是關聯的,通過系統的梳理形成自己的知識體系,打造屬於自己的專屬領域,這也是在Java界立足的根本。

以上這些純屬自己這段時間的瞎想胡扯,大家共勉。

二、Retrofit簡介

retrofit是由square公司開發的。square在github上釋出了很多優秀的Android開源專案。例如:otto(事件匯流排),leakcanary(排查記憶體洩露),android-times-square(日曆控制元件),dagger(依賴注入),picasso(非同步載入圖片),

okhttp(網路請求),retrofit(網路請求)等等。更多square上的開源專案我們可以去square的GitHub進行檢視。

A type-safe HTTP client for Android and Java


可見Retrofit可以應用到Android平臺和Java平臺中,其原始碼中也可看出retrofit2\Platform.java

private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("org.robovm.apple.foundation.NSObject");
      return new IOS();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

可見可以應用在Android、Java8及IOS平臺中,當然在IOS中要基於RoboVM。RoboVM它是一種可以在iOS裝置上執行Java應用程式的技術,這種技術主要還是用於在遊戲開發中。

Retrofit簡化了從Web API下載資料,解析成普通的Java物件(POJO)。

/**
   * Create an implementation of the API endpoints defined by the {@code service} interface.
   * <p>
   * The relative path for a given method is obtained from an annotation on the method describing
   * the request type. The built-in methods are {@link retrofit2.http.GET GET},
   * {@link retrofit2.http.PUT PUT}, {@link retrofit2.http.POST POST}, {@link retrofit2.http.PATCH
   * PATCH}, {@link retrofit2.http.HEAD HEAD}, {@link retrofit2.http.DELETE DELETE} and
   * {@link retrofit2.http.OPTIONS OPTIONS}. You can use a custom HTTP method with
   * {@link HTTP @HTTP}. For a dynamic URL, omit the path on the annotation and annotate the first
   * parameter with {@link Url @Url}.
   * <p>
   * Method parameters can be used to replace parts of the URL by annotating them with
   * {@link retrofit2.http.Path @Path}. Replacement sections are denoted by an identifier
   * surrounded by curly braces (e.g., "{foo}"). To add items to the query string of a URL use
   * {@link retrofit2.http.Query @Query}.
   * <p>
   * The body of a request is denoted by the {@link retrofit2.http.Body @Body} annotation. The
   * object will be converted to request representation by one of the {@link Converter.Factory}
   * instances. A {@link RequestBody} can also be used for a raw representation.
   * <p>
   * Alternative request body formats are supported by method annotations and corresponding
   * parameter annotations:
   * <ul>
   * <li>{@link retrofit2.http.FormUrlEncoded @FormUrlEncoded} - Form-encoded data with key-value
   * pairs specified by the {@link retrofit2.http.Field @Field} parameter annotation.
   * <li>{@link retrofit2.http.Multipart @Multipart} - RFC 2388-compliant multipart data with
   * parts specified by the {@link retrofit2.http.Part @Part} parameter annotation.
   * </ul>
   * <p>
   * Additional static headers can be added for an endpoint using the
   * {@link retrofit2.http.Headers @Headers} method annotation. For per-request control over a
   * header annotate a parameter with {@link Header @Header}.
   * <p>
   * By default, methods return a {@link Call} which represents the HTTP request. The generic
   * parameter of the call is the response body type and will be converted by one of the
   * {@link Converter.Factory} instances. {@link ResponseBody} can also be used for a raw
   * representation. {@link Void} can be used if you do not care about the body contents.
   * <p>
   * For example:
   * <pre>
   * public interface CategoryService {
   *   @POST("category/{cat}/")
   *   Call<List<Item>> categoryList(@Path("cat") String a, @Query("page") int b);
   * }
   * </pre>
   */
  @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
  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, 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 serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

Retrofit依賴於OkHttp,最終的請求響應是在OkHttp中做的,效能之所以高,也是因為okHttp的效能高。

三、OkHttp簡介

android網路框架之OKhttp是一個處理網路請求的開源專案,是安卓端最火熱的輕量級框架,由移動支付Square公司貢獻,用於替代HttpUrlConnection和Apache HttpClient(android API23 6.0裡已移除HttpClient,現在已經打不出來)。
HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP efficiently makes your stuff load faster and saves bandwidth.

OkHttp is an HTTP client that’s efficient by default:
•HTTP/2 support allows all requests to the same host to share a socket.
•Connection pooling reduces request latency (if HTTP/2 isn’t available).
•Transparent GZIP shrinks download sizes.
•Response caching avoids the network completely for repeat requests.

OkHttp perseveres when the network is troublesome: it will silently recover from common connection problems. If your service has multiple IP addresses OkHttp will attempt alternate addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant data centers. OkHttp initiates new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.

Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.

OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.

優勢:允許連線到同一個主機地址的所有請求,提高請求效率共享Socket,減少對伺服器的請求次數通過連線池,減少了請求延遲快取響應資料來減少重複的網路請求 減少了對資料流量的消耗自動處理GZip壓縮

功能:

get,post等請求檔案的上傳下載載入圖片(內部會圖片大小自動壓縮)支援請求回撥,直接返回物件、物件集合支援session的保持
okHttp是直接封裝的Socket,io流是基於Okio的。


四、Okio簡介

Okio is a new library that complements  java.io  and  java.nio  to make it much easier to access, store, and process your data.

Okio庫是一個由square公司開發的,它補充了Java.io和java.nio的不足,以便能夠更加方便,快速的訪問、儲存和處理你的資料。OkHttp的底層也使用該庫作為支援,而在開發中,使用該庫可以大大給你帶來方便。總結:現在第三方開源框架非常之多,以至於我們可以更關注和快速的開發業務。但是這些第三方框架恰恰是我們應該學習的,它們將“簡介“”中說的基本功給剝奪了,像Retrofit用到了註解、動態代理等、OkHttp封裝了Socket、連線池等、Okio是io操作更快捷,其中這些恰恰也是我們應該掌握的。學習Retrofit原始碼使我又重溫了Java網路程式設計、HTTP權威指南、Java IO操作等,其囊括的技術之多,令人歎服!就像做Java Web開發需要理解Spring、Hibernate等框架一樣,在做業務的同時,其核心技術才應該是我們最該掌握和學習的。做個廣告,Spring相關可參考我的Spring實戰系列:http://blog.csdn.net/honghailiang888/article/details/53113853。