Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android http——OkHttp使用詳解

android http——OkHttp使用詳解

編輯:關於Android編程

okhttp已經被google認定為推薦的android請求框架,我們也可以在as中直接加入:
這裡寫圖片描述

okhttp的依賴庫是:

compile 'com.squareup.okhttp:okhttp:2.5'

當然,作為eclipse的開發者來說,就不能使用依賴庫了。

我著重介紹okhttp的使用方法。

我們將okhttp所有的網絡請求方式都寫在RequestHandle類中。

需要注意的幾點是,
1,RequestHandle使用單例。因為okhttp使用單例來操作實例。
2,線程阻塞方式的請求需要在非ui線程中。
3,異步回調結果還處在非ui線程中,所以如果要更新ui,需要handler。

1,將RequestHandle寫成單例模式:

/**
     * 單例請求網絡,只能傳入baseactivity
     */
    private static volatile RequestHandle requestHandle = null;

    public synchronized static RequestHandle getRequestInterface() {
        if (requestHandle == null) {
            synchronized (RequestHandle.class) {
                if (requestHandle == null) {
                    requestHandle = new RequestHandle();
                }
            }
        }
        return requestHandle;
    }

2,定義常量和初始化對象

    //創建隊列,用於異步調用
    private Request request;

    //線程阻塞方式調用
    private Response response;

    //訪問對象
    private Call call;

    //okhttp實例
    private OkHttpClient mOkHttpClient;

    //線程阻塞方式請求的get,post狀態碼
    private final static int GET_INSTANCE = 0;
    private final static int POST_INSTANCE = 1;

    //默認超時時間
    private final static int VALUE_DEFAULT_TIME_OUT = 20 * 1000;

    /**
     * 參數類型
     * "text", 文本
     * "image", 圖片
     * "audio",音頻
     * "video",視頻
     * "object",其他
     */
    private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/x-markdown; charset=utf-8");
    private static final MediaType MEDIA_TYPE_JPG = MediaType.parse("image/png");
    private static final MediaType MEDIA_TYPE_AUDIO = MediaType.parse("audio/mp3");
    private static final MediaType MEDIA_TYPE_VIDEO = MediaType.parse("video/mp4");
    private static final MediaType MEDIA_TYPE_OBJECT = MediaType.parse("application/octet-stream");
    private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");

//給每個網絡請求的標記
    public static final String TAG_DATA = "tag_data";
    public static final String TAG_IMAGE = "tag_image";
    public static final String TAG_FILE = "tag_file";

private RequestHandle() {
        //創建okHttpClient對象
        mOkHttpClient = new OkHttpClient();
        mOkHttpClient.setConnectTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//連接超時
        mOkHttpClient.setReadTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//讀取超時
        mOkHttpClient.setWriteTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//寫入超時
    }

3,線程阻塞的請求,即非異步的。
get請求

/**
     * 線程阻塞的單例發送get請求,線程阻塞的方式需要在非ui線程中
     */
    public void sendGetRequestBlocking(String url) {
        try {
            //創建一個請求
            request = new Request
                    .Builder()
                    .tag(TAG_DATA)
                    .url(url)
                    .build();
            response = mOkHttpClient.newCall(request).execute();
            callBackByEnqueueBlocking(response);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
    }

post請求:

/**
     * 異步的post請求,線程阻塞的方式需要在非ui線程中
     *
     * @param url     請求地址
     * @param builder 請求參數
     */
    public void sendPostRequestBlocking(String url, MultipartBuilder builder) {
        sendPostRequestBlocking(url, builder, null);
    }

post上傳文件:

/**異步的post請求,線程阻塞的方式需要在非ui線程中,可以附帶文件
     * @param url
     * @param builder
     * @param files
     */
    public void sendPostRequestBlocking(String url, MultipartBuilder builder, File[] files) {
        try {
            //builder.addFormDataPart("參數", "值");
            if (files != null && files.length != 0) {
                //遍歷file數組,得到所有file文件
                for (File file : files) {
                    builder.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_OBJECT, file));
                }
            }
            String tag = files == null ? TAG_DATA : TAG_FILE;
            request = new Request.Builder()
                    .url(url)
                    .tag(tag)
                    .post(builder.build())
                    .build();
            response = mOkHttpClient.newCall(request).execute();
            callBackByEnqueueBlocking(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

線程阻塞請求的結果處理:

//隊列請求(線程阻塞)的結果處理方法
    public void callBackByEnqueueBlocking(Response response) {
        try {
            //判斷是否是成功的
            if (response.isSuccessful()) {
                //成功
                //String jsonStr=response.body().string();//字符串,無編碼
                String jsonStr = new String(response.body().bytes(), "UTF-8");//二進制字節數組
                //InputStream inputStream=response.body().byteStream();//輸入流
                try {
                    JSONObject jsonObject = new JSONObject(jsonStr);
                    //解析數據處理
                    //發送數據處理
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                //失敗
                response.code();//失敗碼
                response.message();//失敗信息
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4,異步請求

get請求

/**
     * 異步get請求
     *
     * @param url 請求的哪個接口,異步請求
     */
    public void sendGetRequest(String url) {
        //創建一個Request
        request = new Request.Builder()
                .url(url)
                .tag(TAG_DATA)
                .build();
        call = mOkHttpClient.newCall(request);
        callBackByEnqueue(call);
    }

post請求

 /**
     * 異步的post請求
     */
    public void sendPostRequest(String url, MultipartBuilder builder) {
        sendPostRequest(url, builder, null);
    }

post上傳文件

/** 異步的post請求,傳文件
     * @param url
     * @param builder
     * @param files
     */
    public void sendPostRequest(String url, MultipartBuilder builder, File[] files) {
        //builder.addFormDataPart("參數", "值");
        if (files != null && files.length != 0) {
            //遍歷file數組,得到所有file文件
            for (File file : files) {
                builder.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_OBJECT, file));
            }
        }
        String tag = files == null ? TAG_DATA : TAG_FILE;
        request = new Request.Builder()
                .url(url)
                .tag(tag)
                .post(builder.build())
                .build();
        call = mOkHttpClient.newCall(request);
        callBackByEnqueue(call);
    }

異步請求結果回調處理:

//隊列請求(異步)的結果處理方法
    public void callBackByEnqueue(Call call) {
        //new call
        call = mOkHttpClient.newCall(request);
        //需要注意的是異步回調還是在子線程中,所以如果要更新ui,則記得handler
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                //失敗
            }

            @Override
            public void onResponse(Response response) {
                //響應
                try {
                    if (response.isSuccessful()) {
                        //String jsonStr=response.body().string();//字符串,無編碼
                        String jsonStr = null;//二進制字節數組

                        jsonStr = new String(response.body().bytes(), "UTF-8");

                        //InputStream inputStream=response.body().byteStream();//輸入流
                        try {
                            JSONObject jsonObject = new JSONObject(jsonStr);
                            //解析數據處理
                            //發送數據處理
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    } else {

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

5,設置超時

/**
     * 設置超時
     *
     * @param value
     */
    public void setTimeOut(int value) {
        if (mOkHttpClient == null) return;
        mOkHttpClient.setConnectTimeout(value, TimeUnit.MILLISECONDS);//連接超時
        mOkHttpClient.setReadTimeout(value, TimeUnit.MILLISECONDS);//讀取超時
        mOkHttpClient.setWriteTimeout(value, TimeUnit.MILLISECONDS);//寫入超時
    }

6,清除一個正在請求的操作

/**
     * 取消一個當前正在處理的Call
     * 使用Call.cancel()可以立即停止掉一個正在執行的call。
     * 注意:如果一個線程正在寫請求或者讀響應,將會引發IOException。
     */
    public void cancelByCall() {
        if (call != null) {
            try {
                call.cancel();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

7,清除所有的請求

/**
     * 清楚所有網絡請求
     * 你可以通過tags來同時取消多個請求。
     * 當你構建一請求時,使用RequestBuilder.tag(tag)來分配一個標簽。
     * 之後你就可以用OkHttpClient.cancel(tag)來取消所有帶有這個tag的call。
     *
     * @param isCancelAllRequests
     */
    public void cancelAllRequests(boolean isCancelAllRequests) {
        if (mOkHttpClient != null) {
            try {
                if (isCancelAllRequests) {
                    mOkHttpClient.cancel(TAG_DATA);
                    mOkHttpClient.cancel(TAG_IMAGE);
                    mOkHttpClient.cancel(TAG_FILE);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

8,文件下載、上傳帶進度顯示
因為okhttp自身無法顯示下載進度,所以借用網上的代碼實現下載進度顯示。

下載進度回調

/**
     * 非ui線程回調文件下載進度
     * 這個是非ui線程回調,不可直接操作UI
     */
    final ProgressListener progressResponseListener = new ProgressListener() {
        @Override
        public void onProgress(long bytesRead, long contentLength, boolean done) {
            //長度未知的情況下回返回-1
            if (contentLength != -1 && (100 * bytesRead) / contentLength >= 0) {
                String donePercent = (100 * bytesRead) / contentLength + "%";//上傳進度
            }
        }
    };

下載方法:

/**
     * 下載文件
     *
     * @param url
     */
    public void downloadFile(String url) {
        request = new Request.Builder()
                .url(url)
                .build();
        //包裝Response使其支持進度回調
        ProgressHelper.addProgressResponseListener(mOkHttpClient, progressResponseListener)
                .newCall(request)
                .enqueue(new Callback() {
                    @Override
                    public void onFailure(Request request, IOException e) {
                        String message;
                        if (!NetWorkUtil.isNetworkConnected(UIAppliaction.getInstance())) {
                            //判斷是否是因為沒有網絡的原因
                            message = "網絡不給給力";
                        } else {
                            message = e.getMessage();
                        }
                    }

                    @Override
                    public void onResponse(Response response) throws IOException {
                        String message = "";
                        String url = response.request().url().getPath();
                        //獲得url地址的文件後綴名
                        String filename = url.substring(message.indexOf("."), message.length());
                        InputStream inputStream = response.body().byteStream();//輸入流
                        //通過流保存文件的工具類
                        if (FileUtil.insertSDCardFromInput("文件絕對路徑", filename, inputStream))
                            message = "下載完成";
                        else
                            message = "文件保存失敗";
                    }
                });
    }

至於其中回調的方法我這裡就只貼出代碼。因為是別人處理的代碼,我就分享下載地址。
http://pan.baidu.com/s/1i4GIJtz
ec32
代碼經測試回調進度是正常的。

這些就是基本的okhttp的使用。自己經過封裝後用起來也是非常方便的。這裡分享出來供大家學習。

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