httpURLConnection get請求,post請求.raw請求,文件上傳+參數的工具類

廢話不多說,先上兩個工具類:用作普通的網絡請求使用,文件的下載單獨抽取一個工具類.

public class HttpURLBuild {
    private final String TAG = "HttpURLBuild";

    private String requestUrl = "";
    private final String requestMethod;


    final String PREFIX = "--";                            //前綴
    final String BOUNDARY = UUID.randomUUID().toString();  //邊界標識
    final String CONTENT_TYPE = "multipart/form-data";     //內容類型
    final String LINE_END = "\r\n";                        //換行
    private static final String CHARSET = "utf-8";                         //編碼格式

    //    private HttpClientUtils.OnRequestCallBack callBackListener;
    private HttpClientUtils.OnRequestCallBackBase callBackListenerBase;

    public HttpURLBuild(String requestUrl, String requestMethod) {
        this.requestUrl = requestUrl;
        this.requestMethod = requestMethod;

    }


    HashMap<String, String> headMap = new HashMap<>();
    HashMap<String, File> fileMap = new HashMap<>();

    public HttpURLBuild setHead(String key, String value) {
        headMap.put(key, value);
        return this;
    }

    public HttpURLBuild addFile(String key, File file) {
        fileMap.put(key, file);
        return this;
    }


    Map<String, String> bodyMap = new HashMap<>();
    String rawJson = "";

    public HttpURLBuild addParameter(String key, String value) {
        bodyMap.put(key, value);
        return this;
    }

    public HttpURLBuild addParameter(Map<String, String> parameterMap) {
        bodyMap.putAll(parameterMap);
        return this;
    }

    public HttpURLBuild addRawData(String rawJson) {
        this.rawJson = rawJson;
        return this;
    }

    public HttpURLBuild setCallBack(HttpClientUtils.OnRequestCallBack callBackListener) {
        if (callBackListener == null) {
            return this;
        }
        this.callBackListenerBase = new HttpClientUtils.OnRequestCallBackBase(callBackListener);
        return this;
    }

    StringBuilder builder = new StringBuilder();

    //調用這個方法就開始正真的網絡請求了 之前都是參數的設置,你別管我,讓我看看
    public HttpURLBuild build() {

        if (isCancel) {
            LogUtil.e(TAG, "請求已取消: " + requestUrl);
            return null;
        }
        if (TextUtils.isEmpty(requestUrl)) {
            throw new NullPointerException("請求地址不能爲空");
        }
        if (callBackListenerBase == null) {
            throw new IllegalArgumentException("回調地址不能爲空,請檢查setCallBack()是否調用");
        }
        AppExecutors.getInstance().networkIO().execute(new Runnable() {
            @Override
            public void run() {

                // 現將參數寫入緩衝區等待發送
                DataOutputStream out = null;

                boolean isSuccess = false;
                String message;
                InputStream inputStream = null;
                ByteArrayOutputStream baos = null;
                try {
                    if ("get".equalsIgnoreCase(requestMethod) && bodyMap.size() > 0) {

                        requestUrl += "?";
                        for (String key : bodyMap.keySet()) {
                            requestUrl += key;
                            requestUrl += bodyMap.get(key);
                        }
                    }
                    URL url = new URL(requestUrl);
                    final HttpURLConnection httpURLConnection;
                    httpURLConnection = (HttpURLConnection) url.openConnection();
                    httpURLConnection.setConnectTimeout(60 * 1000);
                    // 設定請求的方法爲"POST",默認是GET
                    httpURLConnection.setReadTimeout(60 * 1000);
                    if ("get".equalsIgnoreCase(requestMethod)) {
                        httpURLConnection.setRequestMethod("GET");
                    } else if ("post".equalsIgnoreCase(requestMethod)) {
                        httpURLConnection.setRequestMethod("POST");
                        // 設置是否向httpUrlConnection輸出,如果是post請求,參數要放在http正文內,因此需要設爲true, 默認是false;
                        httpURLConnection.setDoOutput(true);//這裏設置成true就代表是post請求
                    }
                    /*
                     * 當我們要獲取我們請求的http地址訪問的數據時就是使用connection.getInputStream().read()方式時我們就需要setDoInput(true),
                     * 根據api文檔我們可知doInput默認就是爲true。我們可以不用手動設置了,如果不需要讀取輸入流的話那就setDoInput(false)。
                     * 當我們要採用非get請求給一個http網絡地址傳參 就是使用connection.getOutputStream().write() 方法時我們就需要setDoOutput(true), 默認是false
                     */
                    // 設置是否從httpUrlConnection讀入,默認情況下是true;
                    httpURLConnection.setDoInput(true);
                    //是否使用緩存
                    httpURLConnection.setUseCaches(false);
//                    httpURLConnection.setInstanceFollowRedirects(true);  剛加上的 瞎試的
                    httpURLConnection.setRequestProperty("accept", "*/*");//設置接收數據的格式
                    httpURLConnection.setRequestProperty("Connection", "Keep-Alive");//設置連接方式爲長連接
                    httpURLConnection.setRequestProperty("Charset", "UTF-8");//設置編碼字符格式
                    //設置發送數據的格式
                    httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");//關鍵代碼post的表單提交 application/x-www-form-urlencoded
                    builder.append("請求地址爲-> \n");
                    builder.append(requestUrl + "\n");
                    //不進行轉碼的gson
                    Gson gson = new GsonBuilder().disableHtmlEscaping().create();
                    builder.append("請求頭爲->\n" + gson.toJson(headMap) + "\n");
                    addHeads(httpURLConnection);
                    if ("post".equalsIgnoreCase(requestMethod)) {
                        out = new DataOutputStream(httpURLConnection.getOutputStream());
                        //添加請求體 如果不傳file的話是這種方式進去
                        if (fileMap.size() == 0) {
                            String params = addBodyParams(out);
                        }
                        addRawData(out);
                        if (fileMap.size() > 0) {
                            addFileData(out);
                        }
//                        out.flush();
                    }
                    Log.d(TAG, "請求參數爲-->" + builder.toString());


                    // 發送請求params參數
//                    out.flush();
                    //這個時候纔是真正的將參數發送給服務器的時候  可以不連接getInputStream的時候會自動連接
                    httpURLConnection.connect();
//                    int contentLength = httpURLConnection.getContentLength();
                    if (httpURLConnection.getResponseCode() == 200) {
                        // 會隱式調用connect()
                        inputStream = httpURLConnection.getInputStream();
                        baos = new ByteArrayOutputStream();
                        int readLen;
                        byte[] bytes = new byte[1024];
                        while ((readLen = inputStream.read(bytes)) != -1) {
                            baos.write(bytes, 0, readLen);
                        }
                        String backStr = baos.toString();
                        message = backStr;
                        Log.d(TAG, "請求結果爲-->" + message);
                        isSuccess = true;


                    } else {
                        message = "請求失敗 code:" + httpURLConnection.getResponseCode();
                    }
                } catch (IOException e) {
                    message = e.getMessage();
                    if (!isCancel) {
                        callBackListenerBase.onError(message);
                    }
                    e.printStackTrace();
                } finally {
                    try {
                        if (out != null) {
                            out.close();
                        }
                        if (baos != null) {
                            baos.close();
                        }
                        if (inputStream != null) {
                            inputStream.close();
                        }
                    } catch (IOException e) {
                        message = e.getMessage();
                        if (!isCancel) {
                            callBackListenerBase.onError(message);
                        }
                        e.printStackTrace();
                    }
                }

                if (isCancel) {
                    LogUtil.e(TAG, "請求已取消:數據未回調 " + requestUrl);
                    return;

                } else {
                    if (isSuccess) {
                        callBackListenerBase.onSuccess(message);
                    } else {
                        callBackListenerBase.onError(message);
                    }
                }

            }
        });
        return this;
    }

    private void addFileData(DataOutputStream out) throws IOException {

        //這個是普通的參數
        if (bodyMap.size() > 0) {
            StringBuilder strParams = getStrParams(bodyMap);
            out.write(strParams.toString().getBytes(CHARSET));
            out.flush();
            builder.append(strParams);

        }
        //這個是文件的參數
        if (fileMap != null && fileMap.size() > 0) {
            //文件上傳
            getStrParamsFile(out);
            Log.d(TAG + "文件請求參數爲", builder.toString());
        }
    }

    private void getStrParamsFile(DataOutputStream out) throws IOException {
        StringBuilder fileSb = new StringBuilder();
        for (Map.Entry<String, File> fileEntry : fileMap.entrySet()) {
            fileSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    /**
                     * 這裏重點注意: name裏面的值爲服務端需要的key 只有這個key 纔可以得到對應的文件
                     * filename是文件的名字,包含後綴名的 比如:abc.png
                     */
                    .append("Content-Disposition: form-data; name=\"image\"; filename=\"" + fileMap.get(fileEntry.getKey()).getName() + "\"" + LINE_END)
                    .append("Content-Type: image/jpg" + LINE_END) //此處的ContentType不同於 請求頭 中Content-Type
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END);// 參數頭設置完以後需要兩個換行,然後纔是參數內容
            out.write(fileSb.toString().getBytes(CHARSET));
            out.flush();
            InputStream is = new FileInputStream(fileEntry.getValue());
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            is.close();
            out.writeBytes(LINE_END);
        }
        //請求結束標誌
        out.write((PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes(CHARSET));
        out.flush();
        builder.append(fileSb);
    }


    /**
     * 當傳文件的時候的其他的普通參數設置
     * 對post參數進行編碼處理
     */
    private StringBuilder getStrParams(Map<String, String> strParams) {
        StringBuilder strSb = new StringBuilder();
        for (Map.Entry<String, String> entry : strParams.entrySet()) {
            strSb.append(PREFIX)
                    .append(BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                    .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                    .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                    .append(LINE_END)// 參數頭設置完以後需要兩個換行,然後纔是參數內容
                    .append(entry.getValue())
                    .append(LINE_END);
        }
        return strSb;
    }

    /**
     * raw請求方式的參數設置
     *
     * @param out
     * @throws IOException
     */
    private void addRawData(DataOutputStream out) throws IOException {
        if (!TextUtils.isEmpty(rawJson)) {
            out.write(rawJson.getBytes(CHARSET));
            builder.append("raw參數Wie" + rawJson + "\n");
        }
    }

    /**
     * 這個是普通的表單數據用到的  如果有傳遞文件的就不用這個了  用的是下面那種拼接方式的
     *
     * @param out
     * @return
     * @throws IOException
     */
    @NotNull
    private String addBodyParams(DataOutputStream out) throws IOException {//別動了
        String params = "";

        if (bodyMap.size() > 0) {
            for (String key : bodyMap.keySet()) {
                params = params + key + "=" + bodyMap.get(key) + "&";

            }
            params = params.substring(0, params.length() - 1);

            //需要進行URL的轉碼  這是我看着retorfit返回的結果自己寫的轉碼 也不知道些全了沒
            //對一些特殊的字符需要進行轉碼操作,下面是我發現需要轉碼的字符,有沒有其他的還有待檢驗
            params = params
                    .replace("+", "%2B")
                    .replace("/", "%2F")
                    .replace("\\", "%5C")
                    .replace("\"", "%22")
                    .replace("{", "%7B")
                    .replace("|", "%7C")
                    .replace("}", "%7D")
                    .replace(":", "%3A");


            builder.append("請求參數爲 ->\n" + params + "\n");
            //使用這個可以解決中文亂碼的問題  使用 out.writeBytes();會有中文亂碼的問題
            out.write(params.getBytes(CHARSET));

        }
        return params;
    }

    private void addHeads(HttpURLConnection httpURLConnection) {
        //添加head請求頭
        for (String key : headMap.keySet()) {
            //如果是文件類型的後面追加一個邊界值
            if (TextUtils.equals(key, "Content-Type") && TextUtils.equals(headMap.get(key), CONTENT_TYPE)) {
                httpURLConnection.setRequestProperty(key, headMap.get(key) + ";boundary=" + BOUNDARY);
            } else {
                httpURLConnection.setRequestProperty(key, headMap.get(key));
            }

        }
    }


    private volatile boolean isCancel = false;

    /**
     * 取消網絡請求,其實並不是真正的取消
     * 1.如果還未發起網絡請求就不發起網絡請求
     * 2.如果已發起網絡情趣,則不回調成功的方法,即不處理返回的數據
     */
    public void cancel() {
        isCancel = true;
    }


    private byte[] file2byte(File file) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            bos.flush();
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }


    /**
     * 傳文件的代碼示例
     * <p>
     * <p>
     * public static void postRequest(final Map<String, String> strParams, final Map<String, File> fileParams) {
     * new Thread(new Runnable() {
     *
     * @Override public void run() {
     * HttpURLConnection conn = null;
     * try {
     * URL url = new URL(requestUrl);
     * conn = (HttpURLConnection) url.openConnection();
     * conn.setRequestMethod("POST");
     * conn.setReadTimeout(TIME_OUT);
     * conn.setConnectTimeout(TIME_OUT);
     * conn.setDoOutput(true);
     * conn.setDoInput(true);
     * conn.setUseCaches(false);//Post 請求不能使用緩存
     * //設置請求頭參數
     * conn.setRequestProperty("Connection", "Keep-Alive");
     * conn.setRequestProperty("token", token);
     * conn.setRequestProperty("Charset", "UTF-8");
     * conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
     * //上傳參數
     * DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
     * //getStrParams()爲一個
     * dos.writeBytes(
     *
     * getStrParams(strParams).
     *
     * toString());
     * dos.flush();
     *
     * //文件上傳
     * StringBuilder fileSb = new StringBuilder();
     * for(
     * Map.Entry<String, File> fileEntry :fileParams.entrySet())
     *
     * {
     * fileSb.append(PREFIX)
     * .append(BOUNDARY)
     * .append(LINE_END)
     * //
     * //這裏重點注意: name裏面的值爲服務端需要的key 只有這個key 纔可以得到對應的文件
     * //filename是文件的名字,包含後綴名的 比如:abc.png
     * //
     * .append("Content-Disposition: form-data; name=\"image\"; filename=\"" + fileParams.get(fileEntry.getKey()).getName() + "\"" + LINE_END)
     * .append("Content-Type: image/jpg" + LINE_END) //此處的ContentType不同於 請求頭 中Content-Type
     * .append("Content-Transfer-Encoding: 8bit" + LINE_END)
     * .append(LINE_END);// 參數頭設置完以後需要兩個換行,然後纔是參數內容
     * dos.writeBytes(fileSb.toString());
     * dos.flush();
     * InputStream is = new FileInputStream(fileEntry.getValue());
     * byte[] buffer = new byte[1024];
     * int len = 0;
     * while ((len = is.read(buffer)) != -1) {
     * dos.write(buffer, 0, len);
     * }
     * is.close();
     * dos.writeBytes(LINE_END);
     * }
     * //請求結束標誌
     * dos.writeBytes(PREFIX +BOUNDARY +PREFIX +LINE_END);
     * dos.flush();
     * dos.close();
     *
     * Log.e(TAG,"postResponseCode() = "+conn.getResponseCode());
     * //讀取服務器返回信息
     * if(conn.getResponseCode()==200)
     *
     * {
     * InputStream in = conn.getInputStream();
     * BufferedReader reader = new BufferedReader(new InputStreamReader(in));
     * String line = null;
     * StringBuilder response = new StringBuilder();
     * while ((line = reader.readLine()) != null) {
     * response.append(line);
     * }
     * Log.e(TAG, "run: " + response);
     * }
     * } catch(Exception e){
     * e.printStackTrace();
     * }finally{
     * if(conn!=null){
     * conn.disconnect();
     * }
     * }
     * }
     * }).start();
     * }
     *
     *
     * private static StringBuilder getStrParams(Map<String, String> strParams){
     * StringBuilder strSb=new StringBuilder();
     * for(Map.Entry<String, String> entry:strParams.entrySet()){
     * strSb.append(PREFIX)
     * .append(BOUNDARY)
     * .append(LINE_END)
     * .append("Content-Disposition: form-data; name=\""+entry.getKey()+"\""+LINE_END)
     * .append("Content-Type: text/plain; charset="+CHARSET+LINE_END)
     * .append("Content-Transfer-Encoding: 8bit"+LINE_END)
     * .append(LINE_END)// 參數頭設置完以後需要兩個換行,然後纔是參數內容
     * .append(entry.getValue())
     * .append(LINE_END);
     * }
     * return strSb;
     * }
     *
     */

}

工具類2 主要用作,數據的回調

public class HttpClientUtils {


    /**
     *
     * 使用示例
     * HttpClientUtils().post(Api.API_BASE_URL_2 + "sdk_face_alive")
     *         .setHead("token",XueGuMax.getToken())
     *         .addParameter("serviceName", "real_auth_sdk")
     *         .addParameter("platformNo", XueGuMax.getPlatformNo())
     *         .addParameter("reqData", reqData)
     *         .setCallBack(object : HttpClientUtils.OnRequestCallBack {
     *     override fun onSuccess(json: String?) {
     *         val data = Gson().fromJson(json, AuthResult::class.java)
     *
     *     }
     *     override fun onError(errorMsg: String?) {
     *         Log.e("數據獲取失敗", errorMsg)
     *     }}).build
     */


    private static final String TAG = "HttpClientUtils";

    private Handler mHandler = new Handler(Looper.getMainLooper());

    /**
     * 我自己封住的
     * 此方法爲post請求,異步的網絡請求,回調在主線程
     **/
    public HttpURLBuild post(final String requestUrl) {
        HttpURLBuild httpURLBuild = new HttpURLBuild(requestUrl, "post");
        return httpURLBuild;
    }

    public HttpURLBuild get(final String requestUrl) {
        HttpURLBuild httpURLBuild = new HttpURLBuild(requestUrl, "get");
        return httpURLBuild;
    }
    public interface OnRequestCallBack {
        void onSuccess(String json);

        void onError(String errorMsg);
    }

    public static class OnRequestCallBackBase {
        public OnRequestCallBack OnRequestCallBack;

        public OnRequestCallBackBase(OnRequestCallBack onRequestCallBack) {
            this.OnRequestCallBack = onRequestCallBack;
        }

        public void onSuccess(String json) {

            if (TextUtils.equals(json,"null")||TextUtils.isEmpty(json)) {
                OnRequestCallBack.onError("數據爲空");
                return;
            }
            AppExecutors.getInstance().mainThread().execute(new Runnable() {
                @Override
                public void run() {
//                    Type type = getClass().getGenericSuperclass();

//                    Type trueType = ((ParameterizedType) type).getActualTypeArguments()[0];
                    OnRequestCallBack.onSuccess(json);
                }
            });
        }


        public void onError(String errorMsg) {
            AppExecutors.getInstance().mainThread().execute(new Runnable() {
                @Override
                public void run() {
                    OnRequestCallBack.onError(errorMsg);
                }
            });

        }
    }
}

這裏面的網絡請求默認在子線程,回調在主線程所以使用到了一個線程的工具類也貼出來

public class AppExecutors {
private final Executor mDiskIO;

private final Executor mNetworkIO;

private final Executor mMainThread;
private final ScheduledThreadPoolExecutor schedule;

private static AppExecutors instance;

private static Object object = new Object();

public static AppExecutors getInstance() {
    if (instance == null) {
        synchronized (object) {
            if (instance == null) {
                instance = new AppExecutors();
            }
        }
    }
    return instance;
}

private AppExecutors() {

    this.mDiskIO = Executors.newSingleThreadExecutor(new MyThreadFactory("single"));

    this.mNetworkIO = Executors.newFixedThreadPool(3, new MyThreadFactory("fixed"));

    this.mMainThread = new MainThreadExecutor();

    this.schedule = new ScheduledThreadPoolExecutor(5, new MyThreadFactory("sc"), new ThreadPoolExecutor.AbortPolicy());
}

class MyThreadFactory implements ThreadFactory {

    private final String name;
    private int count = 0;

    MyThreadFactory(String name) {
        this.name = name;
    }

    @Override
    public Thread newThread(@NonNull Runnable r) {
        count++;
        return new Thread(r, name + "-" + count + "-Thread");
    }
}

public Executor diskIO() {
    return mDiskIO;
}

public ScheduledThreadPoolExecutor schedule() {
    return schedule;
}

public Executor networkIO() {
    return mNetworkIO;
}

public Executor mainThread() {
    return mMainThread;
}

private static class MainThreadExecutor implements Executor {
    private Handler mainThreadHandler = new Handler(Looper.getMainLooper());

    @Override
    public void execute(@NonNull Runnable command) {
        mainThreadHandler.post(command);
    }
}

}

下面是使用的示例 (示例代碼用的是kotlin編寫的)

get請求

HttpClientUtils().get(url)
            .setCallBack(object : HttpClientUtils.OnRequestCallBack {
                override fun onSuccess(json: String?) {
                    Log.i("token獲取成功", json.toString())
                    val fromJson = Gson().fromJson(json, TokenBean::class.java)
                    }
                }
                override fun onError(errorMsg: String?) {
                    Log.i("獲取失敗", errorMsg)
                }

            }).build()

post請求(默認使用的格式是表單,如果是其他的文件類型,raw類型等請重新設置.setHead(“Content-Type”, “multipart/form-data”)//設置發送數據的格式)

post請求上傳文件+一些參數

HttpClientUtils().post(Api.API_BASE_URL_2 + "gauss/api/vrc_ocr_sdk.json")
            .setHead("token", XueGuMax.getToken())
            .setHead("Content-Type", "multipart/form-data")//設置發送數據的格式
            .addParameter("serviceName", serviceName)
            .addParameter("platformNo", platformNo)
            .addParameter("reqData", reqData)
            .addParameter("type", type)
            .addFile("image", image)
            .setCallBack(object : HttpClientUtils.OnRequestCallBack {
                override fun onSuccess(json: String?) {
                    val data = Gson().fromJson(json, OcrNoResult::class.java)

                    Log.i("PCarInfo", "請求結果:${data.toString()}")
                }

                override fun onError(errorMsg: String?) {
                    Log.e("數據獲取失敗", errorMsg)
                }
            }).build()

正常的表單數據提交

HttpClientUtils().post(Api.API_BASE_URL_2 + "gauss/vrc_ocr/finalResult.json")
            .setHead("token", XueGuMax.getToken())
            .addParameter("no", no)
            .addParameter("platformNo", platformNo)
            .setCallBack(object : HttpClientUtils.OnRequestCallBack {
                override fun onSuccess(json: String?) {
                    val data = Gson().fromJson(json, CarOcrResult::class.java)
                    Log.i("PCarInfo", "請求結果:${data.toString()}")
                    }
                }

                override fun onError(errorMsg: String?) {
                    Log.e("數據獲取失敗", errorMsg)
                }
            }).build()

raw請求

val gson = Gson()
        val params = HashMap<String, String>()
        params.put("name", "")
        params.put("idCard", "")
        params.put("backUrl", "")
        params.put("time", time)
        params.put("sign", sign)
        params.put("global", "")
        params.put("action", "")
        val strEntity = gson.toJson(params)
        val url = "https://xxxxxx.com/set/identity_verify"

        HttpClientUtils().post(url)
            .setHead("Content-Type", "application/json")
            .addRawData(strEntity)
            .setCallBack(object : HttpClientUtils.OnRequestCallBack {
                override fun onSuccess(json: String?) {
                    Log.i("獲取成功", json.toString())
                    val fromJson = Gson().fromJson(json, ParamUrl::class.java)
                    getToken(fromJson.data, type)
                }

                override fun onError(errorMsg: String?) {
                    Log.i("獲取失敗", errorMsg)
                }

            }).build()

寫的不咋好,網絡能請求通,可以暫時先將就着用,如果不滿意那就自行封裝吧

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