The article directories

    • GET request for OKHTTP3.10
    • POST request for OKHTTP3.10
    • OKHTTP3.10’s GET encapsulates the request
      • Singleton of utility class:
      • Get Synchronization request
      • Get Asynchronous request
      • Concatenation URL of text pass parameter
      • Post Asynchronously requests map parameters to be transmitted
      • Adds parameters to the request body
      • Post Asynchronous request JSON parameter transmission
      • Pass in the request body as JSON
      • Pass the request body as a String
    • File upload:
      • Http-based file upload (passing in filename and key)
      • Http-based file upload, mixing parameters and file requests
    • File download
    • Custom CallBack CallBack MyDataCallBack
    • Custom log interceptor
    • Custom network interceptor
    • Utility class detail code:
    • Source code download address:

As we all know Retrofit is currently the most popular web request framework, and it’s OKHttp that encapsulates it and does the actual work, so it’s important to review OKHttp in order to use Retrofit well. And the latest version OKhttp 3.10.0 and previous version of the operation is not the same, so today to operate a wave to him, from the simple and practical to the encapsulation are in common use way, measurement can be normal use, based on douban film made API test data, detailed source code will have to download address below, and time is pressing, please donate said, Code is the best comment, welcome to fork!

PS: This paper mainly focuses on the following four files:

GET request for OKHTTP3.10

Private void getDouBan1() {//1, create OKHttpClient OKHttpClient = new OKHttpClient (); //2, create a Request Request Request = new request.builder ().url(constant.url).build(); // create a call object call = okHttpClient.newCall(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) { } @Override public void onResponse(Call call, Response response) { if (response.isSuccessful()) { try { res = response.body().string(); ThreadPoolUtil.execute(new Runnable() { @Override public void run() { Log.d(TAG, res); }}); } catch (IOException e) { e.printStackTrace(); }}}}); }Copy the code

POST request for OKHTTP3.10

Private void postDouBan() {//1, create OKHttpClient OKHttpClient = new OKHttpClient (); RequestBody = new formBody.builder ().add("username", "ytf").add("password", "123") .build(); Request request = new Request.Builder().url(Constant.URL).post(requestBody).build(); Okhttpclient.newcall (request).enqueue(new Callback() {@override public void onFailure(Call Call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { try { res = response.body().string(); ThreadPoolUtil.execute(new Runnable() { @Override public void run() { // Looper.prepare(); // Toast.makeText(MainActivity.this, res, Toast.LENGTH_SHORT).show(); Log.d(TAG, res); EventBus.getDefault().post(res); }}); } catch (IOException e) { e.printStackTrace(); }}}}); }Copy the code

RequestBody example:

OKHTTP3.10’s GET encapsulates the request

Singleton of utility class:

/** * public OkHTTPManger() {okHttpClient = new okHttpClient (); } public static OkHTTPManger getInstance() { if (instance == null) { synchronized (OkHTTPManger.class) { if (instance ==  null) { instance = new OkHTTPManger(); } } } return instance; }Copy the code

Get Synchronization request

Response.body ().string() to get the returned string ** @param URL * @return */ public string getSyncBackString(String url) { Request request = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); ResponseStr = response.body().string(); return responseStr; } catch (IOException e) {logger. e("GET sync request parse as String exception "+ e.tostring ()); e.printStackTrace(); } return null; }Copy the code
/** * get sync request * Response.body ().bytes() get the returned binary byte array ** @param url * @return */ public byte[] getSyncBackByteArray(String url) { Request request = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); Byte [] responseStr = response.body().bytes(); return responseStr; } catch (IOException e) {logger. e("GET sync request parse as byte array exception "+ e.tostring ()); e.printStackTrace(); } return null; }Copy the code
/** * get Sync request * response.body().bytestream () to get the returned binary stream ** @param URL * @return */ public InputStream getSyncBackByteStream(String url) { Request request = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); InputStream responseStr = response.body().bytestream (); return responseStr; } catch (IOException e) {logger. e("GET sync request parse as String exception "+ e.tostring ()); e.printStackTrace(); } return null; }Copy the code
/** * get sync request * response.body().bytestream () to get the returned binary stream ** @param url * @return */ public Reader getSyncBackCharReader(String url) { Request request = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(request); try { Response response = call.execute(); ResponseStr = response.body().charstream (); return responseStr; } catch (IOException e) {logger. e("GET Reader exception "+ e.tostring ()); e.printStackTrace(); } return null; }Copy the code

Get Asynchronous request

/** * get Async request does not pass arguments * Response.body ().string() returns the string * async return value cannot update UI, To open a new thread @ url param * @ return * * * / public String getAsynBackStringWithoutParms (String url, final MyDataCallBack myDataCallBack) { final Request request = new Request.Builder() .url(url) .build(); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) {// logger. e("GET String failed "+ e.tostring ()); myDataCallBack.requestFailure(request, e); } @Override public void onResponse(Call call, Response response) throws IOException { responseStrGETAsyn = response.body().string(); try { myDataCallBack.requestSuccess(responseStrGETAsyn); } catch (Exception e) { e.printStackTrace(); Logger.e("GET async request parsing exception for String failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("GET async request parse toString Exception "+ e.tostring ()); e.printStackTrace(); } return responseStrGETAsyn; }Copy the code
/** * get async request to pass parameters (can pass null) * response.body().string() return string * async return value cannot update UI, To open a new thread @ url param * @ return * * * / public String getAsynBackStringWithParms (String url, Map < String, the String > params, final MyDataCallBack myDataCallBack) { if (params == null) { params = new HashMap<>(); } // Request url (baseUrl+ parameter) String doUrl = urlJoint(url, params); Final Request Request = new request.builder ().url(doUrl) //.header("Cookie").build(); final Request Request = new request.builder ().url(doUrl) //.header("Cookie").build(); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) {// logger. e("GET String failed "+ e.tostring ()); myDataCallBack.requestFailure(request, e); } @Override public void onResponse(Call call, Response response) throws IOException { responseStrGETAsyn = response.body().string(); try { myDataCallBack.requestSuccess(responseStrGETAsyn); } catch (Exception e) { e.printStackTrace(); Logger.e("GET async request parsing exception for String failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("GET async request parse toString Exception "+ e.tostring ()); e.printStackTrace(); } return responseStrGETAsyn; }Copy the code

Concatenation URL of text pass parameter

/** * @param url path * @param params * @return */ private static String url (String url, Map<String, String> params) { StringBuilder realURL = new StringBuilder(Constant.URL); realURL = realURL.append(url); boolean isFirst = true; if (params == null) { params = new HashMap<>(); } else { Set<Map.Entry<String, String>> entrySet = params.entrySet(); for (Map.Entry<String, String> entry : entrySet) { if (isFirst && ! url.contains("?" )) { isFirst = false; realURL.append("?" ); } else { realURL.append("&"); } realURL.append(entry.getKey()); realURL.append("="); if (entry.getValue() == null) { realURL.append(" "); } else { realURL.append(entry.getValue()); } } } return realURL.toString(); }Copy the code

##OKHTTP3.10 POST encapsulates the request

Post Asynchronously requests map parameters to be transmitted

/** * post async request map pass * response.body().string() return string * async return value cannot update UI, To start a new thread * * @param URL * @return */ public String postAsynBackString(String url, Map<String, String> params, final MyDataCallBack myDataCallBack) { RequestBody requestBody; if (params == null) { params = new HashMap<>(); } FormBody.Builder builder = new FormBody.Builder(); /** * Add the parameter to traverse */ addMapParmsToFromBody(params, Builder); requestBody = builder.build(); String realURL = urlJoint(url, null); Final Request Request = new request.builder ().url(realURL).post(requestBody).build(); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) { myDataCallBack.requestFailure(request, e); } @Override public void onResponse(Call call, Response response) throws IOException { responseStrGETAsyn = response.body().string(); / / here can also be resolved as a byte [], Reader, InputStream try {myDataCallBack. RequestSuccess (responseStrGETAsyn); } catch (Exception e) { e.printStackTrace(); Logger.e("POST async request parsing exception for String failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("POST async request parse toString Exception "+ e.tostring ()); e.printStackTrace(); } return responseStrGETAsyn; }Copy the code

Adds parameters to the request body

private void addMapParmsToFromBody(Map<String, String> params, FormBody.Builder builder) { for (Map.Entry<String, String> map : params.entrySet()) { String key = map.getKey(); String value; / * * * judge whether value is empty * / if (map) getValue () = = null) {value = ""; } else { value = map.getValue(); } /** * add key and value to formBody */ builder.add(key, value); }}Copy the code

Post Asynchronous request JSON parameter transmission

/** * POST async request JSON parameter * Response.body ().string() return string * async return value cannot update UI, * * @param url * @return */ public String postAsynRequireJson(String url, Map<String, String> params, final MyDataCallBack myDataCallBack) { if (params == null) { params = new HashMap<>(); String mapToJson = new Gson().tojson (params); final String realURL = urlJoint(url, null); final Request request = buildJsonPostRequest(realURL, mapToJson); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) { myDataCallBack.requestFailure(request, e); } @Override public void onResponse(Call call, Response response) throws IOException { responseStrGETAsyn = response.body().string(); / / here can also be resolved as a byte [], Reader, InputStream try {myDataCallBack. RequestSuccess (responseStrGETAsyn); } catch (Exception e) { e.printStackTrace(); Logger.e("POST async request parsing exception for String failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("POST async request parse toString Exception "+ e.tostring ()); e.printStackTrace(); } return responseStrGETAsyn; }Copy the code

Effect:

Pass in the request body as JSON

Json_POST Request parameters ** @param URL URL * @param json json * @return requestBody */ private Request buildJsonPostRequest(String url, String json) { // RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json); RequestBody requestBody = RequestBody.create(JSON, json); return new Request.Builder().url(url).post(requestBody).build(); }Copy the code

Pass the request body as a String

/** * String_POST Request parameter ** @param URL URL * @param json json * @return requestBody */ private Request buildStringPostRequest(String url, String json) { RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, json); return new Request.Builder().url(url).post(requestBody).build(); }Copy the code

File upload:

Http-based file upload (passing in filename and key)

/** * HTTP-based file upload (passing filename and key) * custom callback interface via addFormDataPart ** @param URL the Path part of the URL * @param myDataCallBack * File is passed to the server as the request body. * @param fileKey: "pic.png" */ private void upLoadMultiFileSimple(String url, String fileName, String fileKey, final MyDataCallBack myDataCallBack) { File file = new File(Environment.getExternalStorageDirectory(), fileName); RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart(fileKey, fileName, fileBody) .build(); final String realURL = urlJoint(url, null); final Request request = new Request.Builder() .url(realURL) .post(requestBody) .build(); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) { myDataCallBack.requestFailure(request, e); } @Override public void onResponse(Call call, Response response) throws IOException { try { myDataCallBack.requestSuccess(responseStrGETAsyn); } catch (Exception e) { e.printStackTrace(); Logger.e("POST asynchronous file upload failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("POST async file upload Exception "+ e.tostring ()); e.printStackTrace(); }}Copy the code

Http-based file upload, mixing parameters and file requests

/** * HTTP-based file upload (passed file array and key) mix parameters and file requests ** addFormDataPart allows you to add multiple uploaded files ** @param URL Path part of the URL * @param myDataCallBack * @param files Upload file * @param fileKeys Upload file key set */ private void upLoadMultiFile(String) url, File[] files, String[] fileKeys, Map<String, String> params, final MyDataCallBack myDataCallBack) { if (params == null) { params = new HashMap<>(); } final String realURL = urlJoint(url, null); FormBody.Builder builder = new FormBody.Builder(); addMapParmsToFromBody(params, builder); RequestBody requestBody = builder.build(); MultipartBody.Builder multipartBody = new MultipartBody.Builder(); multipartBody.setType(MultipartBody.ALTERNATIVE) .addPart(requestBody); if (files ! = null) { RequestBody fileBody = null; for (int i = 0; i < files.length; i++) { File file = files[i]; String fileName = file.getName(); fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file); ContentType multipartBody.addPart(Headers. Of (" content-disposition ", "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""), fileBody); } } final Request request = new Request.Builder() .url(realURL) .post(multipartBody.build()) .build(); Call call = okHttpClient.newCall(request); try { myDataCallBack.onBefore(request); Call. Enqueue (new Callback() {@override public void onFailure(call, Callback); IOException e) { myDataCallBack.requestFailure(call.request(), e); } @Override public void onResponse(Call call, Response response) { try { myDataCallBack.requestSuccess(response.body().string()); } catch (Exception e) { e.printStackTrace(); Logger.e("POST asynchronous file upload failed "+ e.tostring ()); }}}); myDataCallBack.onAfter(); } catch (Exception e) {logger. e("POST async file upload Exception "+ e.tostring ()); e.printStackTrace(); } } *************************************************************************************** private String guessMimeType(String fileName) { FileNameMap fileNameMap = URLConnection.getFileNameMap(); String contentTypeFor = fileNameMap.getContentTypeFor(fileName); if (contentTypeFor == null) { contentTypeFor = "application/octet-stream"; } return contentTypeFor; }Copy the code

File download

/** * File download * @param URL path Path * @param destFileDir Folder path of local storage * @param myDataCallBack Customized callback interface */ private void downLoadFileAsyn(final String url, final String destFileDir, final MyDataCallBack myDataCallBack){ String realURL=urlJoint(url,null); Request request=new Request.Builder() .url(realURL) .build(); Call call=okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { myDataCallBack.requestFailure(call.request(),e); } @Override public void onResponse(Call call, Response response) { InputStream is = null; byte[] buf = new byte[2048]; int len = 0; FileOutputStream fos = null; is = response.body().byteStream(); File file = new File(destFileDir, getFileName(url)); try { fos = new FileOutputStream(file); while ((len = is.read(buf)) ! = -1) { fos.write(buf, 0, len); } fos.flush(); } catch (IOException e) {logger. e(" error: ", LLDB message ()); e.printStackTrace(); }finally { if (is ! = null) { try { is.close(); } catch (IOException e) {logger. e(" LLDB: ", LLDB message ()); e.printStackTrace(); } } if (fos ! = null) { try { fos.close(); } catch (IOException e) {logger. e(" LLDB: ", LLDB message ()); e.printStackTrace(); }}} / / if the downloaded file is successful, the first parameter is the file's absolute path sendSuccessResultCallback (file. The getAbsolutePath (), myDataCallBack); myDataCallBack.requestSuccess(response.body().toString()); }}); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% private String getFileName(String url) { int separatorIndex = url.lastIndexOf("/"); return (separatorIndex < 0) ? url : url.substring(separatorIndex + 1, url.length()); } &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& private void sendSuccessResultCallback(final String absolutePath, final MyDataCallBack myDataCallBack) { ThreadPoolUtil.execute(new Runnable() { @Override public void run() { if (myDataCallBack! =null){ myDataCallBack.requestSuccess(absolutePath); }}}); }Copy the code

Custom CallBack CallBack MyDataCallBack

package com.app.ytf.httpdemo.okhttp; import com.google.gson.internal.$Gson$Types; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import okhttp3.Request; /** * @author ytf Public abstract class MyDataCallBack<T> {public abstract class MyDataCallBack<T> {public Abstract class MyDataCallBack<T> {public Abstract class MyDataCallBack<T> {public Abstract class MyDataCallBack<T> { public MyDataCallBack() { // mType=getSuperclassTypeParameter(getClass()); } / * * * by reflecting back to the Type of * @ param ttf_subclass * @ return * / static Type getSuperclassTypeParameter (Class <? > subclass) { Type superclass = subclass.getGenericSuperclass(); If (superclass instanceof Class) {throw new RuntimeException(" unknown return type "); } ParameterizedType parameterized = (ParameterizedType) superclass; return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); }} @param request */ public void onBefore(request request); public abstract void requestSuccess(T result); // void requestSuccess(Reader result) throws Exception; // void requestSuccess(InputStream result) throws Exception; // void requestSuccess(byte[] result) throws Exception; public abstract void requestFailure(Request request, IOException e); Public void onAfter(); public void onAfter(); }Copy the code

Custom log interceptor

package com.app.ytf.httpdemo.okhttp; import com.orhanobut.logger.Logger; import java.io.IOException; import java.util.Locale; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; /** * @author ytf * Custom interceptor * Chain object can get the Request object of the current Request, and then we can do the second processing of the Request, and finally generate the Request, and then send the Request to the server over the network. Public class HeaderInterceptor implements Interceptor {@override public Response Intercept (Chain Chain) throws IOException { Request request = chain.request(); Logger.d(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); long t1 = System.nanoTime(); okhttp3.Response response = chain.proceed(chain.request()); long t2 = System.nanoTime(); Logger.d(String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); okhttp3.MediaType mediaType = response.body().contentType(); String content = response.body().string(); Logger.json(content); Response response1=chain.proceed(request); Logger.d(" Return response: ", response1.tostring ()); Return the response. NewBuilder (). The header (" Authorization ", "intercept request Authorization header information"). The body (okhttp3. ResponseBody. Create (mediaType, content)) .build(); }}Copy the code

Custom network interceptor

package com.app.ytf.httpdemo.okhttp; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import com.app.ytf.httpdemo.APP; import java.io.IOException; import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; /** * @author ytf * Set network interceptor, Public class CacheInterceptor implements Interceptor {@override public Response Intercept (Chain Chain) throws IOException { Request request = chain.request(); if (! isNetworkConnected()) { request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response originalResponse = chain.proceed(request); If (isNetworkConnected()) {if (isNetworkConnected()) { So you can do a uniform setting here (note out) String cacheControl = request.cachecontrol ().toString(); return originalResponse.newBuilder() .header("Cache-Control", cacheControl) //.header("Cache-Control", "Max-age =3600").removeheader ("Pragma") // removeHeader information, because the server does not support it, it will return some interference information, the following does not take effect. Build (); } else {//1. No Cache: cache-control: no-cache or cache-control: max-age=0 //2. If you want to display data first, in the request. Cache-control: only-if-cached int maxAge = 60 * 60; return originalResponse.newBuilder() .header("Cache-Control", "public, only-if-cached, max-age=" + maxAge) .removeHeader("Pragma") .build(); }} /** * @return */ private Boolean isNetworkConnected() {ConnectivityManager connectivity = (ConnectivityManager) APP.getInstance() .getSystemService(Context.CONNECTIVITY_SERVICE); if (null ! = connectivity) { NetworkInfo info = connectivity.getActiveNetworkInfo(); if (null ! = info && info.isConnected()) { if (info.getState() == NetworkInfo.State.CONNECTED) { return true; } } } return false; }}Copy the code

Utility class detail code:

package com.app.ytf.httpdemo.okhttp;

import android.os.Environment;

import com.app.ytf.httpdemo.APP;
import com.app.ytf.httpdemo.util.Constant;
import com.app.ytf.httpdemo.util.ThreadPoolUtil;
import com.google.gson.Gson;
import com.google.gson.internal.$Gson$Types;
import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.FileNameMap;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.sql.ParameterMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @author ytf
 */
public class OkHTTPManger {
    private static OkHttpClient okHttpClient;
    private volatile static OkHTTPManger instance;//防止多个线程同时访问
    //提交json数据
    private static final MediaType JSON = MediaType.parse("application/json;charset=utf-8");
    //提交字符串数据
    private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown;charset=utf-8");
    private static String responseStrGETAsyn;

    private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
// 使用getCacheDir()来作为缓存文件的存放路径(/data/data/包名/cache) ,
// 如果你想看到缓存文件可以临时使用 getExternalCacheDir()(/sdcard/Android/data/包名/cache)。
    private static File cacheFile;
    private static Cache cache;

    public OkHTTPManger() {
//        if (APP.getInstance().getApplicationContext().getCacheDir()!=null){
//            cacheFile = new File(APP.getInstance().getCacheDir(), "Test");
//            cache = new Cache(cacheFile, 1024 * 1024 * 10);
//        }

        okHttpClient = new OkHttpClient();
        okHttpClient.newBuilder()
//                .addInterceptor(new HeaderInterceptor())
//                .addNetworkInterceptor(new CacheInterceptor())
//                .cache(cache)
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .cookieJar(new CookieJar() {
                    @Override
                    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                        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>();
//自动管理Cookie发送Request都不用管Cookie这个参数也不用去response获取新Cookie什么的了。还能通过cookieStore获取当前保存的Cookie。
                    }
                });
    }


    /**
     * 懒汉式加锁单例模式
     * @return
     */
    public static OkHTTPManger getInstance() {
        if (instance == null) {
            synchronized (OkHTTPManger.class) {
                if (instance == null) {
                    instance = new OkHTTPManger();
                }
            }
        }
        return instance;
    }


    /**
     * get同步请求不需要传参数
     * 通过response.body().string()获取返回的字符串
     *
     * @param url
     * @return
     */
    public String getSyncBackString(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            // 将response转化成String
            String responseStr = response.body().string();
            return responseStr;
        } catch (IOException e) {
            Logger.e("GET同步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get同步请求
     * 通过response.body().bytes()获取返回的二进制字节数组
     *
     * @param url
     * @return
     */
    public byte[] getSyncBackByteArray(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            // 将response转化成String
            byte[] responseStr = response.body().bytes();
            return responseStr;
        } catch (IOException e) {
            Logger.e("GET同步请求解析为byte数组异常" + e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get同步请求
     * 通过response.body().byteStream()获取返回的二进制字节流
     *
     * @param url
     * @return
     */
    public InputStream getSyncBackByteStream(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            // 将response转化成String
            InputStream responseStr = response.body().byteStream();
            return responseStr;
        } catch (IOException e) {
            Logger.e("GET同步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get同步请求
     * 通过response.body().byteStream()获取返回的二进制字节流
     *
     * @param url
     * @return
     */
    public Reader getSyncBackCharReader(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            // 将response转化成String
            Reader responseStr = response.body().charStream();
            return responseStr;
        } catch (IOException e) {
            Logger.e("GET同步请求解析为Reader异常" + e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get异步请求不传参数
     * 通过response.body().string()获取返回的字符串
     * 异步返回值不能更新UI,要开启新线程
     *
     * @param url
     * @return
     */
    public String getAsynBackStringWithoutParms(String url, final MyDataCallBack myDataCallBack) {

        final Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
//                 Logger.e("GET异步请求为String失败"+e.toString());
                    myDataCallBack.requestFailure(request, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    responseStrGETAsyn = response.body().string();
                    try {
                        myDataCallBack.requestSuccess(responseStrGETAsyn);

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("GET异步请求为String解析异常失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("GET异步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return responseStrGETAsyn;
    }

    /**
     * get异步请求传参数(可以传null)
     * 通过response.body().string()获取返回的字符串
     * 异步返回值不能更新UI,要开启新线程
     *
     * @param url
     * @return
     */
    public String getAsynBackStringWithParms(String url, Map<String, String> params, final MyDataCallBack myDataCallBack) {
        if (params == null) {
            params = new HashMap<>();
        }
        // 请求url(baseUrl+参数)
        String doUrl = urlJoint(url, params);
        final Request request = new Request.Builder()
                .url(doUrl)
//                .header("Cookie", "自动管理更新需要携带的Cookie")
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
//                 Logger.e("GET异步请求为String失败"+e.toString());
                    myDataCallBack.requestFailure(request, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    responseStrGETAsyn = response.body().string();
                    try {
                        myDataCallBack.requestSuccess(responseStrGETAsyn);

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("GET异步请求为String解析异常失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("GET异步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return responseStrGETAsyn;
    }

    /**
     * post异步请求map传参
     * 通过response.body().string()获取返回的字符串
     * 异步返回值不能更新UI,要开启新线程
     *
     * @param url
     * @return
     */
    public String postAsynBackString(String url, Map<String, String> params, final MyDataCallBack myDataCallBack) {
        RequestBody requestBody;
        if (params == null) {
            params = new HashMap<>();
        }

        FormBody.Builder builder = new FormBody.Builder();
        /**
         * 在这对添加的参数进行遍历
         */
        addMapParmsToFromBody(params, builder);

        requestBody = builder.build();
        String realURL = urlJoint(url, null);
        //结果返回
        final Request request = new Request.Builder()
                .url(realURL)
                .post(requestBody)
                .build();
        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    myDataCallBack.requestFailure(request, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    responseStrGETAsyn = response.body().string();//此处也可以解析为byte[],Reader,InputStream
                    try {
                        myDataCallBack.requestSuccess(responseStrGETAsyn);

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("POST异步请求为String解析异常失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("POST异步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return responseStrGETAsyn;
    }

    private void addMapParmsToFromBody(Map<String, String> params, FormBody.Builder builder) {
        for (Map.Entry<String, String> map : params.entrySet()) {
            String key = map.getKey();
            String value;
            /**
             * 判断值是否是空的
             */
            if (map.getValue() == null) {
                value = "";
            } else {
                value = map.getValue();
            }
            /**
             * 把key和value添加到formbody中
             */
            builder.add(key, value);
        }
    }

    /**
     * post异步请求json传参
     * 通过response.body().string()获取返回的字符串
     * 异步返回值不能更新UI,要开启新线程
     *
     * @param url
     * @return
     */
    public String postAsynRequireJson(String url, Map<String, String> params, final MyDataCallBack myDataCallBack) {

        if (params == null) {
            params = new HashMap<>();
        }
        // 将map转换成json,需要引入Gson包
        String mapToJson = new Gson().toJson(params);
        final String realURL = urlJoint(url, null);
        final Request request = buildJsonPostRequest(realURL, mapToJson);
        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    myDataCallBack.requestFailure(request, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    responseStrGETAsyn = response.body().string();//此处也可以解析为byte[],Reader,InputStream
                    try {
                        myDataCallBack.requestSuccess(responseStrGETAsyn);

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("POST异步请求为String解析异常失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("POST异步请求解析为String异常" + e.toString());
            e.printStackTrace();
        }
        return responseStrGETAsyn;
    }

    /**
     * Json_POST请求参数
     *
     * @param url  url
     * @param json json
     * @return requestBody
     */
    private Request buildJsonPostRequest(String url, String json) {
//        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
        RequestBody requestBody = RequestBody.create(JSON, json);
        return new Request.Builder().url(url).post(requestBody).build();
    }

    /**
     * String_POST请求参数
     *
     * @param url  url
     * @param json json
     * @return requestBody
     */
    private Request buildStringPostRequest(String url, String json) {
        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, json);
        return new Request.Builder().url(url).post(requestBody).build();
    }

    /**
     * @param url    实际URL的path
     * @param params
     * @return
     */
    private static String urlJoint(String url, Map<String, String> params) {
        StringBuilder realURL = new StringBuilder(Constant.URL);
        realURL = realURL.append(url);
        boolean isFirst = true;
        if (params == null) {
            params = new HashMap<>();
        } else {
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            for (Map.Entry<String, String> entry : entrySet) {
                if (isFirst && !url.contains("?")) {
                    isFirst = false;
                    realURL.append("?");
                } else {
                    realURL.append("&");
                }
                realURL.append(entry.getKey());
                realURL.append("=");
                if (entry.getValue() == null) {
                    realURL.append(" ");
                } else {
                    realURL.append(entry.getValue());
                }

            }
        }

        return realURL.toString();
    }

    /**
     * 基于http的文件上传(传入文件名和key)
     * 通过addFormDataPart
     *
     * @param url            URL的Path部分
     * @param myDataCallBack 自定义回调接口
     *                       将file作为请求体传入到服务端.
     * @param fileKey        文件传入服务器的键"image"
     * @fileName: "pic.png"
     */
    private void upLoadMultiFileSimple(String url, String fileName, String fileKey, final MyDataCallBack myDataCallBack) {
        File file = new File(Environment.getExternalStorageDirectory(), fileName);
        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart(fileKey, fileName, fileBody)
                .build();
        final String realURL = urlJoint(url, null);
        final Request request = new Request.Builder()
                .url(realURL)
                .post(requestBody)
                .build();

        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    myDataCallBack.requestFailure(request, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        myDataCallBack.requestSuccess(responseStrGETAsyn);

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("POST异步文件上传失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("POST异步文件上传异常" + e.toString());
            e.printStackTrace();
        }
    }

    /**
     * 基于http的文件上传(传入文件数组和key)混合参数和文件请求
     * 通过addFormDataPart可以添加多个上传的文件
     *
     * @param url            URL的Path部分
     * @param myDataCallBack 自定义回调接口
     *                       将file作为请求体传入到服务端.
     * @param files          上传的文件
     * @param fileKeys       上传的文件key集合
     */
    private void upLoadMultiFile(String url, File[] files, String[] fileKeys, Map<String, String> params, final MyDataCallBack myDataCallBack) {
        if (params == null) {
            params = new HashMap<>();
        }
        final String realURL = urlJoint(url, null);
        FormBody.Builder builder = new FormBody.Builder();
        addMapParmsToFromBody(params, builder);
        RequestBody requestBody = builder.build();
        MultipartBody.Builder multipartBody = new MultipartBody.Builder();
        multipartBody.setType(MultipartBody.ALTERNATIVE)
                .addPart(requestBody);

        if (files != null) {
            RequestBody fileBody = null;
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                String fileName = file.getName();
                fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
                //TODO 根据文件名设置contentType
                multipartBody.addPart(Headers.of("Content-Disposition",
                        "form-data; name=\"" + fileKeys[i] + "\"; filename=\"" + fileName + "\""),
                        fileBody);
            }

        }

        final Request request = new Request.Builder()
                .url(realURL)
                .post(multipartBody.build())
                .build();

        Call call = okHttpClient.newCall(request);
        try {
            myDataCallBack.onBefore(request);
            // 请求加入调度
            call.enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    myDataCallBack.requestFailure(call.request(), e);
                }

                @Override
                public void onResponse(Call call, Response response)  {
                    try {
                        myDataCallBack.requestSuccess(response.body().string());

                    } catch (Exception e) {
                        e.printStackTrace();
                        Logger.e("POST异步文件上传失败" + e.toString());
                    }

                }
            });

            myDataCallBack.onAfter();
        } catch (Exception e) {
            Logger.e("POST异步文件上传异常" + e.toString());
            e.printStackTrace();
        }
    }

    private String guessMimeType(String fileName) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(fileName);
        if (contentTypeFor == null) {
            contentTypeFor = "application/octet-stream";
        }
        return contentTypeFor;

    }

    /**
     * 文件下载
     * @param url path路径
     * @param destFileDir 本地存储的文件夹路径
     * @param myDataCallBack 自定义回调接口
     */
    private void downLoadFileAsyn(final String url, final String destFileDir, final MyDataCallBack myDataCallBack){
        String realURL=urlJoint(url,null);
        Request request=new Request.Builder()
                .url(realURL)
                .build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                myDataCallBack.requestFailure(call.request(),e);

            }

            @Override
            public void onResponse(Call call, Response response) {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                is = response.body().byteStream();
                File file = new File(destFileDir, getFileName(url));
                try {
                    fos = new FileOutputStream(file);
                    while ((len = is.read(buf)) != -1)
                    {
                        fos.write(buf, 0, len);
                    }
                    fos.flush();
                } catch (IOException e) {
                    Logger.e("文件下载异常:",e.getMessage());
                    e.printStackTrace();
                }finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            Logger.e("文件流关闭异常:",e.getMessage());
                            e.printStackTrace();
                        }
                    }
                    if (fos != null) {
                        try {
                            fos.close();
                        } catch (IOException e) {
                            Logger.e("文件流关闭异常:",e.getMessage());
                            e.printStackTrace();
                        }
                    }

                }

                //如果下载文件成功,第一个参数为文件的绝对路径
                sendSuccessResultCallback(file.getAbsolutePath(), myDataCallBack);

                myDataCallBack.requestSuccess(response.body().toString());

            }
        });
    }

    private String getFileName(String url) {
        int separatorIndex = url.lastIndexOf("/");
        return (separatorIndex < 0) ? url : url.substring(separatorIndex + 1, url.length());

    }

    private void sendSuccessResultCallback(final String absolutePath, final MyDataCallBack myDataCallBack) {
        ThreadPoolUtil.execute(new Runnable() {
            @Override
            public void run() {
                if (myDataCallBack!=null){
                    myDataCallBack.requestSuccess(absolutePath);
                }
            }
        });
    }

}
Copy the code

Source code download address:

Click download demo