okHttp3學習總結

OkHttp3

okHttp3 是一個 Android的基於Http的網絡開源框架,是由 square 公司開發。

現在網上比較推薦的兩個 Android 網絡開源框架,一個是 okHttp,另一個是 Retrofit
,而 Retrofit 是根據 okHttp封裝的框架。所以關於Android網絡部分,okHttp是必須要學習的一個知識。

[官網地址] (https://github.com/square/okhttp)

項目中引用 okHttp3 只需要在 app 的 build.gradle 中引用 compile ‘com.squareup.okhttp3:okhttp:3.6.0’ 即可。

[慕課網洪洋大神的okHttp視頻]
(http://www.imooc.com/learn/764)
[參考的簡書文章]
(http://www.jianshu.com/p/964bb1b2d345)
[參考的CSDN文章]
(http://blog.csdn.net/itachi85/article/details/51190687)

1.okHttp3的基本用法
首先,不管是 Get 請求還是 Post 請求,同步或者異步,okHttp3的請求總體分爲三步:

  1. 構造出一個okHttp3下的Request對象
  2. 通過這個Request對象,構造出一個Call對象
  3. 調用這個call對象的同步或者異步方法執行網絡訪問

示例如下:

    //構造出一個Request對象,address是訪問的服務器地址,當前示例是get方式訪問
    Request request = new Request.Builder().url(address).get().build();
    //通過上面的request對象,構造出一個Call對象,sOkHttpClient爲全局的OkHttpClient對象
    Call call = sOkHttpClient.newCall(request);
    //call執行enqueue(異步)或者execute(同步),callback爲異步執行時的回調對象
    call.enqueue(callback);

2.okHttp3下的Get請求方式

 /**
 * Get請求方法
 * @param view
 */
public void doGet(View view){
    String address = baseUrl + "login?username=hblolj&password=123456";
    HttpUtils.sendOkHttpRequestByGet(address, new Callback() {
        //請求失敗的回調
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }
        //請求成功的回調
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //拿到服務器返回的數據
            final String result = response.body().string();
            Log.i(TAG, "onResponse: " + result);
            //因爲是enqueue異步執行,所以只有在主線程中纔可以更新UI
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText(result);
                }
            });
        }
    });
}

/**
 * HttpUtils中的Get請求方法
 * @param address  get方式的請求地址
 * @param callback 回調對象
 */
public static void sendOkHttpRequestByGet(String address , Callback callback){
    Request request = new Request.Builder().url(address).get().build();
    Call call = sOkHttpClient.newCall(request);
    call.enqueue(callback);
}

3.okHttp3下的Post請求方式(鍵值對型)

Tips:post請求默認的類型是:application/x-www-form-urlencoded

  //在OkHttp3的源碼中FormBody 的源碼    
  private static final MediaType CONTENT_TYPE =
  MediaType.parse("application/x-www-form-urlencoded");

根據 MediaType 的類型,post選擇對上傳的數據是否進行編碼處理。如果爲 multipart/form-data 類型表示上傳的是文件,則不用進行編碼處理。

/**
 * Post請求方法
 * @param view
 */
public void doPost(View view){
    //登錄接口
    String address = baseUrl + "login";
    Map<String, String> map = new HashMap<>();
    map.put("username", "hblolj");
    map.put("password", "123456");
    HttpUtils.sendOkHttpRequestByPost(address, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            final String result = response.body().string();
            Log.i(TAG, "onResponse: " + result);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText(result);
                }
            });
        }
    }, map);
}

/**
 * HttpUtils中的post請求方法
 * @param address  post請求的地址
 * @param callback 回調對象
 * @param maps     post請求的參數
 */
public static void sendOkHttpRequestByPost(String address, Callback callback, Map<String, String> maps){
    //根據參數中的maps拼裝出RequestBody,用來保存參數,默認的MediaType
    RequestBody requestBody = new FormBody.Builder()
            .add("username", maps.get("username"))
            .add("password", maps.get("password"))
            .build();
    //將請求地址與請求參數設置給Request
    Request request = new Request.Builder().url(address).post(requestBody).build();
    //構造Call對象
    Call call = sOkHttpClient.newCall(request);
    //異步執行網絡訪問
    call.enqueue(callback);
}

4.okHttp3下的Post請求方式(String型)

/**
 * Post請求上傳字符串
 * @param view
 */
public void doPostString(View view){
    String address = baseUrl + "postString";
    HttpUtils.sendOkHttpRequestByPostString(address, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            final String result = response.body().string();
            Log.i(TAG, "onResponse: " + result);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText(result);
                }
            });
        }
    }, "我是通過PostString傳遞的字符內容");
}

/**
 * Post上傳字符串方法
 * @param address  服務器地址
 * @param callback 回調對象
 * @param value    上傳的字符串
 */
public static void sendOkHttpRequestByPostString(String address, Callback callback, String value){
    //相對於鍵值對類型,這裏指定了MediaType
    RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), value);
    //構造Request
    Request request = new Request.Builder().url(address).post(requestBody).build();
    //構造Call
    Call call = sOkHttpClient.newCall(request);
    //異步執行
    call.enqueue(callback);
}

5.okHttp3下的Post請求方式(File型)

/**
 * Post請求上傳文件
 * @param view
 */
public void doPostFile(View view){
    String address = baseUrl + "postFile";
    //從內存卡獲取文件
    File file = new File(Environment.getExternalStorageDirectory(), "shareimg.png");
    if (!file.exists()){
        Log.i(TAG, "文件不存在");
        tv_result.setText("文件不存在!");
        return;
    }
    HttpUtils.sendOkHttpRequestByPostFile(address, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            final String result = response.body().string();
            Log.i(TAG, "onResponse: " + result);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText(result);
                }
            });
        }
    }, file);
}

/**
 * Post方法上傳文件
 * @param address   完整的請求地址
 * @param callback  回調對象
 * @param file      上傳的文件對象
 */
public static void sendOkHttpRequestByPostFile(String address, Callback callback, File file){
    //指定了MediaType爲application/octet-stream,並且傳入File生成requestBody
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    //構造Request
    Request request = new Request.Builder().url(address).post(requestBody).build();
    //構造Call
    Call call = sOkHttpClient.newCall(request);
    //異步執行
    call.enqueue(callback);
}

6.okHttp3下的文件上傳

/**
 * okHttp3下的文件上傳
 * @param view
 */
public void doUpload(View view){
    String address = baseUrl + "uploadFile";
    File file = new File(Environment.getExternalStorageDirectory(), "tagPicture.jpg");
    if (!file.exists()){
        Log.i(TAG, "文件不存在");
        tv_result.setText("文件不存在!");
        return;
    }
    HttpUtils.sendOkHttpRequestByUpload(address, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            final String result = response.body().string();
            Log.i(TAG, "onResponse: " + result);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText(result);
                }
            });
        }
    }, file);
}

/**
 * okHttp3下的文件時上傳
 * @param address  訪問的地址
 * @param callback 回調對象
 * @param file     上傳的文件
 */
public static void sendOkHttpRequestByUpload(String address, Callback callback, File file){
    //構造MultipartBody(複合Body)
    MultipartBody multipartBody = new MultipartBody.Builder()
            //配置上傳的類型
            .setType(MultipartBody.FORM)
            //上傳的普通鍵值對
            .addFormDataPart("username", "hblolj")
            .addFormDataPart("password", "123456")
            //參數對應爲name, fileName, reuqestBody
            .addFormDataPart("picture", "一張照片.jpg",
                //構造文件類型RequestBody
                RequestBody.create(MediaType.parse("application/octet-stream"), file))
            .build();
    //構造Request
    Request request = new Request.Builder().url(address).post(multipartBody).build();
    //構造Call
    Call call = sOkHttpClient.newCall(request);
    //異步執行
    call.enqueue(callback);
}

7.okHttp3下的文件下載

/**
 * okhttp3下的文件下載
 * @param view
 */
public void doDownloadFile(View view){
    //下載地址
    String address = baseUrl + "files/picture.jpg";
    HttpUtils.sendOkHttpRequestByDownloadFile(address, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.i(TAG, "onFailure: " + e.getMessage());
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //拿到服務器下載文件的輸入流
            InputStream is = response.body().byteStream();
            //本地新建文件
            File file = new File(Environment.getExternalStorageDirectory(), "一張照片6666.jpg");
            //拿到新建文件的輸出流
            FileOutputStream fout = new FileOutputStream(file);
            //模板代碼,將下載文件的輸入流寫到新建文件
            int len = 0;
            byte[] buf = new byte[128];
            while((len = is.read(buf)) != -1){
                fout.write(buf, 0, len);
            }
            fout.flush();
            fout.close();
            is.close();

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv_result.setText("下載成功");
                }
            });
        }
    });
}

/**
 * okhttp3下的文件下載
 * 找到下載地址,就是普通的Get訪問
 * @param address  下載地址
 * @param callback 回調對象
 */
public static void sendOkHttpRequestByDownloadFile(String address, Callback callback){
    Request request = new Request.Builder().url(address).get().build();

    Call call = sOkHttpClient.newCall(request);
    call.enqueue(callback);
}

8.okHttp3下的Session保持與緩存

/**
 * 全局的okHttpClient
 */
private static OkHttpClient sOkHttpClient = new OkHttpClient.Builder().cookieJar(new CookieJar() {

        private Map<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
            //根據請求的host保存cookies到內存,達到session的保存
            Log.d("HttpUtils", "host: " + url.host());
            cookieStore.put(url.host(), cookies);
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
            List<Cookie> cookies = cookieStore.get(url.host());
            return cookies!=null?cookies : new ArrayList<Cookie>();
        }
    })
        //設置連接超時時間
        .connectTimeout(1500, TimeUnit.MILLISECONDS)
        .readTimeout(2000, TimeUnit.MILLISECONDS)
        .writeTimeout(2000, TimeUnit.MILLISECONDS)
        //設置保存緩存的文件以及大小限制
        .cache(new Cache(file , 10*1024*1024))
        .build();   

9.okHttp3的框架封裝

參考開始的推薦文章

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