1. 程式人生 > >OkGo___簡單易用的OkHttp網路請求封裝庫

OkGo___簡單易用的OkHttp網路請求封裝庫

引入

compile 'com.lzy.net:okgo:3.0.4'

初始化

//沒有特殊需要的話,最簡單的初始化就可以了
OkGO.getInstance()
    .init(application); 
//定製
        //設定全域性請求頭,不支援中文,不允許有中文字元
        HttpHeaders headers = new HttpHeaders();
        headers.put("commonHeaderKey1", "commonHeaderValue1");
        headers.put("commonHeaderKey2"
, "commonHeaderValue2"); //設定全域性請求引數,支援中文 HttpParams params = new HttpParams(); params.put("commonParamsKey1", "commonParamsValue1"); params.put("commonParamsKey2", "這裡支援中文引數"); //使用OkGo的攔截器 OkHttpClient.Builder builder = new OkHttpClient.Builder(); HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("meee"
); //日誌的列印範圍 loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY); //在logcat中的顏色 loggingInterceptor.setColorLevel(Level.INFO); //預設是Debug日誌型別 builder.addInterceptor(loggingInterceptor); //設定請求超時時間,預設60秒 builder.readTimeout(OkGo.DEFAULT
_MILLISECONDS, TimeUnit.MILLISECONDS); //讀取超時時間 builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); //寫入超時時間 builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); //連線超時時間 //okhttp預設不儲存cookes/session資訊,需要自己的設定 //builder.cookieJar(new CookieJarImpl(new SPCookieStore(this))); //使用sp保持cookie,如果cookie不過期,則一直有效 // builder.cookieJar(new CookieJarImpl(new DBCookieStore(this))); //使用資料庫保持cookie,如果cookie不過期,則一直有效 builder.cookieJar(new CookieJarImpl(new MemoryCookieStore())); //使用記憶體儲存cookie,退出後失效 OkGo.getInstance() .init(this) .setOkHttpClient(builder.build())//不設定則使用預設 .setCacheMode(CacheMode.NO_CACHE)//設定快取模式 .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)//設定快取時間,預設永不過期 .setRetryCount(3);//請求超時重連次數,預設3次 // .addCommonHeaders(headers) // .addCommonParams(params);

基本使用

get請求

        OkGo.<String>get("url")//
                .tag(this)
                .params("adKind","1")//傳入請求引數
                .cacheKey("cachekey")//作為快取的key
                .cacheMode(CacheMode.NO_CACHE)//設定快取模式

                //StringCallback只返回成功
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {

                    }
                    @Override//介面卡模式,可以不實現該方法
                    public void onError(Response<String> response) {

                    }
                });

Post請求

                OkGo.<LzyResponse<ServerModel>>post(Urls.URL_METHOD)//
                        .tag(this)//
                        .headers("header1", "headerValue1")//
                        .params("param1", "paramValue1")//
                        .params("param2", "paramValue2")//
                        .params("param3", "paramValue3")//
                        .isMultipart(true)         //強制使用 multipart/form-data 表單上傳(只是演示,不需要的話不要設定。預設就是false)
                        .execute(new DialogCallback<LzyResponse<ServerModel>>(this) {
                            @Override
                            public void onSuccess(Response<LzyResponse<ServerModel>> response) {
                                handleResponse(response);
                            }

                            @Override
                            public void onError(Response<LzyResponse<ServerModel>> response) {
                                handleError(response);
                            }
                        });

下載圖片

        OkGo.<Bitmap>get(url)
                .execute(new BitmapCallback() {
                    @Override
                    public void onSuccess(Response<Bitmap> response) {
                        Log.d("meee", getClass() + ":\n" + "onSuccess:" + response.body().getHeight());
                        iv.setImageBitmap(response.body());
                    }
                });

下載檔案

        OkGo.<File>get("http://url.9xiazaiqi.com/down/蒼之紀元-電腦版@295_21797.exe")
                .execute(new FileCallback(/*可以傳入路徑和名稱*/) {
                    @Override
                    public void onSuccess(Response<File> response) {
                        Log.d("meee",getClass()+":\n"+"test:"+(response.body().length()/1024)+"KB");
                    }

                    //progress.fraction獲取當前的下載進度
                    @Override
                    public void downloadProgress(Progress progress) {
                        Log.d("meee",getClass()+":\n"+"progress:"+progress.fraction);
                    }
                });

上傳String文字

一般此種用法用於與伺服器約定的資料格式,當使用該方法時,params中的引數設定是無效的,所有引數均需要通過需要上傳的文字中指定,此外,額外指定的header引數仍然保持有效。

預設會攜帶以下請求頭

Content-Type: text/plain;charset=utf-8
如果你對請求頭有自己的要求,可以使用這個過載的形式,傳入自定義的content-type

// 比如上傳xml資料,這裡就可以自己指定請求頭 upString("這是要上傳的長文字資料!", MediaType.parse("application/xml"))

這裡寫圖片描述

基本斷點續傳

上傳檔案

上傳檔案支援檔案與引數一起同時上傳,也支援一個key上傳多個檔案,以下方式可以任選

特別要注意的是

1). 很多人會說需要在上傳檔案到時候,要把Content-Type修改掉,變成multipart/form-data,就像下面這樣的。其實在使用OkGo的時候,只要你添加了檔案,這裡的的Content-Type不需要你手動設定,OkGo自動新增該請求頭,同時,OkGo也不允許你修改該請求頭。

Content-Type: multipart/form-data; boundary=f6b76bad-0345-4337-b7d8-b362cb1f9949
2). 如果沒有檔案,那麼OkGo將自動使用以下請求頭,同樣OkGo也不允許你修改該請求頭。

Content-Type: application/x-www-form-urlencoded

3). 如果你的伺服器希望你在沒有檔案的時候依然使用multipart/form-data請求,那麼可以使用.isMultipart(true)這個方法強制修改,一般來說是不需要強制的。

這裡寫圖片描述
這裡寫圖片描述

取消請求

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //取消指定tag的請求
        OkGo.getInstance().cancelTag(this);
        //取消全部請求
        OkGo.getInstance().cancelAll();
        //取消OkHttpClient的全部請求
        OkGo.cancelAll(new OkHttpClient());
        OkGo.cancelTag(new OkHttpClient(),"且指定tag");
    }

同步請求

        //NetworkOnMainThreadException
        //方式一:
        try {
            okhttp3.Response response = OkGo.<String>get(url)
                    .params("adKind", "1")
                    .execute();

            Log.d("meee",getClass()+":\n"+"test:"+response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //方式二,也許可以轉換成Rxjava的Obser
        Call<String> call = OkGo.<String>get(url)
                .params("adKind", "1")
                .converter(new StringConvert())
                .adapt();
        try {
            Response<String> execute = call.execute();
            Log.d("meee",getClass()+":\n"+"execute:"+execute.body());
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("meee",getClass()+":\n"+"Exception:");
        }
    }

Cookies管理

cookie是有作用域的,他繫結的是url對應的host,比如你的請求兩個介面,一個是 www.domain1.com 一個是 www.domain2.com 那麼這個時候,domain1所具有的cookie是不會自動在domain2中攜帶的,如果一定要讓他們兩個都可以用,那麼需要手動設定,方法請看下面的cookie互動。

檢視okgo管理的cookie中,某個url所對應的全部cookie

CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore();
HttpUrl httpUrl = HttpUrl.parse("http://server.jeasonlzy.com/OkHttpUtils/method/");
List<Cookie> cookies = cookieStore.getCookie(httpUrl);
showToast(httpUrl.host() + "對應的cookie如下:" + cookies.toString());
檢視okgo管理的所有cookie

CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore();
List<Cookie> allCookie = cookieStore.getAllCookie();
showToast("所有cookie如下:" + allCookie.toString());
手動向okgo管理的cookie中,新增一些自己的cookie,那麼以後滿足條件時,okgo就會帶上這些cookie

HttpUrl httpUrl = HttpUrl.parse("http://server.jeasonlzy.com/OkHttpUtils/method/");
Cookie.Builder builder = new Cookie.Builder();
Cookie cookie = builder.name("myCookieKey1").value("myCookieValue1").domain(httpUrl.host()).build();
CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore();
cookieStore.saveCookie(httpUrl, cookie);
手動把okgo管理的cookie移除

HttpUrl httpUrl = HttpUrl.parse("http://server.jeasonlzy.com/OkHttpUtils/method/");
CookieStore cookieStore = OkGo.getInstance().getCookieJar().getCookieStore();
cookieStore.removeCookie(httpUrl);

支援Rxjava2

內部使用了
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
但還是需要新增
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
用於切換執行緒
        OkGo.<String>get("url")//
                .tag(this)
                .params("adKind", "1")
                .converter(new StringConvert())
                .adapt(new ObservableResponse<String>())
                .compose(ThreadSwitch.<Response<String>>switchSchedulers())
                .subscribe(new Consumer<Response<String>>() {
                    @Override
                    public void accept(@NonNull Response<String> stringResponse) throws Exception {
                        Log.d("meee",getClass()+":\n"+"stringResponse:"+stringResponse.body());
                    }
                });

作者的convert還是太複雜了,咱們還是用普通的用Gson好了

               //解析父類泛型的真實型別(有侷限性,繼承後就無法解析到)
                Type genType = getClass().getGenericSuperclass();
                type = ((ParameterizedType) genType).getActualTypeArguments()[0];
//引入Gson
compile 'com.google.code.gson:gson:2.8.2'
//自定義轉換器
public class JsonConvert<T> implements Converter<T> {
    Class<T> clazz;
    private static Gson mGson;
    public static Gson getGson(){
        if (mGson==null){
            synchronized (JsonConvert.class){
                if (mGson==null){
                    mGson=new Gson();
                }
            }
        }
        return mGson;
    }

    public JsonConvert(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public T convertResponse(Response response) throws Throwable {
        Gson gson =getGson();
        JsonReader jsonReader = new JsonReader(response.body().charStream());
        T t = gson.fromJson(jsonReader, clazz);
        return t;
    }
}
//
        OkGo.<JsonBean>get("url")//
                .tag(this)
                .params("adKind", "1")
                //核心就是converter和adapter兩個方法,之後就和普通的rxava一樣了
                .converter(new JsonConvert<JsonBean>(JsonBean.class))
                .adapt(new ObservableResponse<JsonBean>())
                .compose(ThreadSwitch.<Response<JsonBean>>switchSchedulers())//封裝了執行緒切換
                .map(new Function<Response<JsonBean>, JsonBean>() {
                    @Override
                    public JsonBean apply(@NonNull Response<JsonBean> jsonBeanResponse) throws Exception {
                        return jsonBeanResponse.body();
                    }
                })
                .subscribe(new Consumer<JsonBean>() {
                    @Override
                    public void accept(@NonNull JsonBean jsonBean) throws Exception {
                        Log.d("meee",getClass()+":\n"+"jsonBean:"+jsonBean);
                    }
                });

上傳和下載的功能拓展

compile 'com.lzy.net:okserver:2.0.5'
//下載
https://github.com/jeasonlzy/okhttp-OkGo/wiki/OkDownload
//上傳
https://github.com/jeasonlzy/okhttp-OkGo/wiki/OkUpload