OkHttp與Retrofit的作用和聯繫

一、OkHttp

1、OkHttp的介紹

OkHttp是一個關於網絡請求的第三方類庫,其中封裝了網絡請求的get、post等操作的底層實現,是Android端目前最爲火熱的網絡請求框架之一。

2、OkHttp的使用

在Android Studio中不需要下載專門的jar包,直接在gradle中添加依賴,如下所示:

compile 'com.squareup.okhttp3:okhttp:3.10.0'

3、get方法請求

  • 同步請求 同步請求需要在子線程中執行,並且在執行結果返回後在UI線程中修改UI。下面是一個get請求的代碼例子:
new Thread(new Runnable() {
    @Override
    public void run() {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url("http:www.taobao.com").build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                Log.d("ABC", "response=" + response.body().toString());
                // 轉到UI線程去修改UI
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

get同步請求分爲三步: 首先使用new創建OkHttpClient對象。 然後調用OkHttpClient對象的newCall方法生成一個Call對象,該方法接收一個Request對象,Request對象存儲的就是我們的請求URL和請求參數。 最後執行Call對象的execute方法,得到Response對象,這個Response對象就是返回的結果。

  • 異步請求 異步方法不需要開啓一個線程執行操作,但是要注意的是最終的回調方法是在子線程執行的,所以我們要修改UI也必須要在UI線程中進行修改。看一下下面這個例子:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.tabao.com").build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d("ABC", "error");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            Log.d("ABC", "response=" + response.body().toString());
            // 轉到UI線程去修改UI
        }
    }
});

get異步請求分爲三步: 首先使用new創建OkHttpClient對象。 然後調用OkHttpClient對象的newCall方法生成一個Call對象,該方法接收一個Request對象,Request對象存儲的是我們的請求URL和請求參數。 最後執行Call對象的enqueue方法,該方法接收一個Callback回調對象,在回調對象的onResponse方法中拿到Response對象,這就是返回的結果。

總結:get的同步方法和異步方法的差別在於同步方法需要手動開啓一個線程執行,而異步方法不需要(其實是使用了內部的線程)。

4、post方法請求

  • 同步請求 post方法的同步請求和get方法的同步請求幾乎是一樣的,看下面的例子,並和上面的get的同步請求進行對比:
new Thread(new Runnable() {
    @Override
    public void run() {
        OkHttpClient client = new OkHttpClient();
        FormBody.Builder formBody = new FormBody.Builder();
        formBody.add("bookName", "Android Art");
        Request request = new Request.Builder().url("http:www.taobao.com").post(formBody.build()).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                Log.d("ABC", "response=" + response.body().toString());
                // 轉到UI線程去修改UI
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

對比:post方法的同步請求和get方法的同步請求的區別在於,post方法生成Request對象時多執行了post(RequestBody)方法,而RequestBody對象的子類是FormBody類,所以可以使用FormBody對象創建鍵值對參數。

再深入一步,爲什麼post請求需要執行post方法,而且get請求不用呢?我們看一下post方法裏面執行了什麼操作?

public Builder post(RequestBody body) {
    return method("POST", body);
}

返回了method方法的執行結果,這裏傳遞了一個“POST”字符串,看一下method方法的執行:

public Builder method(String method, RequestBody body) {
  if (method == null) throw new NullPointerException("method == null");
  if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
  if (body != null && !HttpMethod.permitsRequestBody(method)) {
    throw new IllegalArgumentException("method " + method + " must not have a request body.");
  }
  if (body == null && HttpMethod.requiresRequestBody(method)) {
    throw new IllegalArgumentException("method " + method + " must have a request body.");
  }
  this.method = method;
  this.body = body;
  return this;
}

這裏將“POST"字符串傳遞給了Builder對象的method變量,而Builder的默認構造函數中將method變量賦值爲"GET"。到這裏就水落石出了,原來Request.Builder對象創建時,默認就是get請求,所以get請求就不用設置get方法了,而post請求則需要修改method變量的值爲"POST"。

  • 異步請求 post方法的異步請求和get方法的異步請求也是非常相似的,區別也是同步請求的區別,所以直接看例子吧:
OkHttpClient client = new OkHttpClient();
FormBody.Builder formBody = new FormBody.Builder();
formBody.add("bookName", "Android Art");
Request request = new Request.Builder().url("http://www.tabao.com").post(formBody.build()).build();
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d("ABC", "error");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            Log.d("ABC", "response=" + response.body().toString());
            // 轉到UI線程去修改UI
        }
    }
});

二、Retrofit

1、Retrofit的介紹

Retrofit是一個RESTful的HTTP網絡請求框架,它是基於OkHttp的。它是通過註解配置網絡參數的,支持多種數據的解析和序列化(Gson、Json、Xml等,並且對RxJava也是支持的。下面是Retrofit和OkHttp的聯繫圖(圖來自於https://blog.csdn.net/carson_ho/article/details/73732076):

Retrofit和OkHttp的聯繫

 

可以看到App應用層是通過Retrofit請求網絡,然後使用Retrofit接口層封裝請求參數、Header、URL等信息,然後由OkHttp完成後續的和服務器的交互。 而服務器返回響應數據後,也是先返回給OkHttp,然後OkHttp將原始結果返回給Retrofit,Retrofit根據用戶的需求對原始數據進行解析封裝,並返回給App應用層。

 

2、Retrofit的使用

2.1 添加依賴庫

在Android Studio中Retrofit庫的依賴,由於其還依賴了OkHttp庫,所以同時需要添加OkHttp的依賴。

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.8.1'
複製代碼

2.2 添加網絡請求的接口

Retrofit使用註解的方式描述和配置網絡請求參數。實際上是運用動態代理的方式將註解翻譯成一個Http請求,然後執行該請求。基本的結構如下:

public interface GitHubService {
  @GET("getUserData")
  Call<User> getCall();
}

User.java

public class User {
    private int userId;
    private String userName;
    private ExInfo exInfo;

    private static class ExInfo {
        private String from;
        private String birthDay;
    }

    public void show() {
        Log.d("ABC", "userId=" + userId);
        Log.d("ABC", "userName=" + userName);
        Log.d("ABC", "from=" + exInfo.from);
        Log.d("ABC", "birthday=" + exInfo.birthDay);
    }
}

注意項: 1、這是一個接口(Interface)不是一個類(class)。 2、其中可以創建不同的接口方法。 3、每一個接口方法和接口方法的參數必須使用註解的方式標註,否則會報錯。 4、請求方法有GET、POST、PUT、HEAD、DELETE等。 5、方法的返回類型必須爲Call,xxx是接收數據的類(可以是我們自定義的類,也可以是ResponseBody)。 6、User中字段的名字必須和後臺Json定義的字段名是一致的,這樣Json才能解析成功。

2.3 創建Retrofit對象

Retrofit retrofit = new Retrofit.Builder().baseUrl("http://10.75.114.138:8081/")
                .addConverterFactory(GsonConverterFactory.create()).build(); //設置網絡請求的Url地址
                .addConverterFactory(GsonConverterFactory.create()) //設置數據解析器
                .build();

網絡請求的地址:創建Retrofit對象時通過baseUrl()設置+網絡請求接口的註解設置。 addConverterFactory(GsonConverterFactory.create())的作用是設置數據解析器,它可以解析Gson、JsonObject、JsonArray這三種格式的數據。

2.4 創建網絡請求接口實例

// 創建 網絡請求接口 的實例
GitHubServiceRequest request = retrofit.create(GitHubService.class);

//對 發送請求 進行封裝
Call<Reception> call = request.getCall();

2.5 發送網絡請求

同步請求:

// 發送網絡請求(同步)
Response<Reception> response = call.execute();

異步請求:

call.enqueue(new Callback<User>() {
    //請求成功後回調
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        //處理請求結果
        User user = response.body();
        if(user != null) {
            user.show();
        }
    }

    //請求失敗後回調
    @Override
    public void onFailure(Call<User> call, Throwable throwable) {
        System.out.println("請求失敗");
    }
});

3、總結

Retrofit的一個RESTful風格的網絡請求框架,其下一層的實現也是OkHttp,所以其原理和OkHttp的一樣的,只是在OkHttp的上面封裝了一層,使請求接口和數據解析更加簡潔明瞭。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章