OkHttp的封装和使用详解

其实一直想写这篇文章的,为什么不写呢?因为不想写,不要咬我.我要开始装逼了.接触okhttp是在2015年6月份左右,这已经过去了几年了,但是我对于它的爱犹如滔滔江水,连绵不绝,现在介绍一下,几年前我自己封装的okhttp工具类,拢共就几个类.不会对于造成学习的困扰.开始喽…


因为我已经把它封装为一个工具类,并上传到jcenter仓库,所以大家使用的话,直接gradle应用即可

Github地址

compile 'cn.yuan.yu:library:1.0.2'

使用方法

第一步:初始化我们的工具类

public class MyApplication extends Application {
    private static   Handler mainHandler;
    private static Context instance;
    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        mainHandler = new Handler();
        /**
         * 初始化okhttputils
         * 第一个参数是是否提交json数据的形式还是表单的形式
         * 第二份参数是请求返回的标识code
         * 第三个参数是请求返回的正确的code值
         * 第四个参数是请求返回的提示信息key
         * 第五个参数是为了同步线程的问题
         * 第六个参数是为了弹出提示信息的上下文
         */
        OkHttpUtilsConfig.getInstance().init(false, "resultcode", "100", "msg", mainHandler,this);
    }
}

第二步,直接调用使用喽,就是这么简单粗暴

  JSONObject jsonObject = new JSONObject();
                jsonObject.put("username", username);
                jsonObject.put("password", pwd);
                L.d("登录", jsonObject.toJSONString());
                RequestPacket requestPacket = new RequestPacket();
                requestPacket.url = ConstantUrl.getBaseUrl();
                requestPacket.addArgument("data", jsonObject.toJSONString());
                requestPacket.addArgument("query", "login");
                OkHttpUtil.Request(RequestPacket.POST,requestPacket,new ResponseListener<RegistGetVCodeBean>() {
                    @Override
                    public void onSuccess(RegistGetVCodeBean registGetVCodeBean) {
                    //todo somethiing
                    }

                    @Override
                    public void onFailure(String responseresult) {
                      //todo somethiing
                    }
                });

源码分析

第一步:看下我们封装的参数实体类

package cn.yuan.yu.library.bean;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by yukuo on 2015/6/18.
 * 这是一个请求实体类
 */
public class RequestPacket implements Serializable {
    public static final int POST = 1000, GET = 1001;// 定义两个请求类型
    public String url;// 请求的网络地址
    public Map<String, Object> arguments = new HashMap<>();// 请求参数
    public Map<String, String> headers = new HashMap<>();// 请求头

    /**
     * 这是一个添加请求参数的方法
     *
     * @param key
     * @param value
     */
    public void addArgument(String key, Object value) {
        arguments.put(key, value);
    }

    /**
     * 这是一个添加头信息参数的方法
     *
     * @param key
     * @param value
     */
    public void addHeader(String key, String value) {
        headers.put(key, value);
    }

    /**
     * 这是一个根据键获取参数值得方法
     *
     * @param key
     * @return
     */
    public Object getArgument(String key) {
        return arguments.get(key);
    }

    /**
     * 这是一个根据键获取头信息值得方法
     *
     * @param key
     * @return
     */
    public String getHeader(String key) {
        return headers.get(key);
    }
}

第二步看下我们封装的配置工具类

package cn.yuan.yu.library;

import android.content.Context;
import android.os.Handler;

/**
 * Created by yukuoyuan on 2017/3/14.
 * 这是一个okhttp的配置类
 */

public class OkHttpUtilsConfig {
    //返回编码key
    private String ResultCodeKey = "";
    //返回编码正确值
    private String ResultCodeValue = "";
    //返回错误信息值
    private String ResultMsgKey = "";
    //是否提交json数据//否的话使用表单提交的形式
    private boolean isPostJson = false;
    //用于同步线程
    private Handler mainHandler;
    //是否展示和日志
    private boolean isShowLog;
    //上下文
    private Context context;

    /**
     * 设置是否使用提交json的形式
     * 不设置的话则使用提交表单的形式提交
     *
     * @param postJson 是否
     */
    public void setPostJson(boolean postJson) {
        isPostJson = postJson;
    }

    /**
     * 设置返回的编码的key
     *
     * @param resultCodeKey key
     */
    public void setResultCodeKey(String resultCodeKey) {
        ResultCodeKey = resultCodeKey;
    }

    /**
     * 设置返回正确的正确的value
     *
     * @param resultCodeValue
     */
    public void setResultCodeValue(String resultCodeValue) {
        ResultCodeValue = resultCodeValue;
    }

    /**
     * 设置返回信息的字段key
     *
     * @param resultMsgKey key
     */
    public void setResultMsgKey(String resultMsgKey) {
        ResultMsgKey = resultMsgKey;
    }

    /**
     * 这是一个初始化okhttputils的方法
     */
    public void init(boolean postJson, String resultCodeKey, String resultCodeValue, String resultMsgKey, Handler mainHandler, Context context) {
        setPostJson(postJson);
        setResultCodeKey(resultCodeKey);
        setResultCodeValue(resultCodeValue);
        setResultMsgKey(resultMsgKey);
        setMainHandler(mainHandler);
        setContext(context);
    }
    public boolean isPostJson() {
        return isPostJson;
    }


    public String getResultCodeKey() {
        return ResultCodeKey;
    }


    public String getResultCodeValue() {
        return ResultCodeValue;
    }


    public String getResultMsgKey() {
        return ResultMsgKey;
    }

    public Handler getMainHandler() {
        return mainHandler;
    }

    public void setMainHandler(Handler mainhandler) {
        this.mainHandler = mainhandler;
    }

    public boolean isShowLog() {
        return isShowLog;
    }

    public void setShowLog(boolean showLog) {
        isShowLog = showLog;
    }

    public Context getContext() {
        return context;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    private static OkHttpUtilsConfig sInstance;

    private OkHttpUtilsConfig() {
    }

    public static OkHttpUtilsConfig getInstance() {
        if (sInstance == null) {
            synchronized (OkHttpUtilsConfig.class) {
                if (sInstance == null) {
                    sInstance = new OkHttpUtilsConfig();
                }
            }
        }
        return sInstance;
    }

}

第三步看下我们封装的回调接口

Ps:做了解析json的操作

package cn.yuan.yu.library.listener;

/**
 * Created by yukuo on 2016/3/18.
 * 这是一个服务器响应的监听器
 */
public abstract class ResponseListener<T> {
    /**
     * 这是一个返回正确信息的回调方法
     *
     * @param t
     */
    public abstract void onSuccess(T t);

    /**
     * 这是一个返回错误信息的回调方法
     *
     * @param responseresult
     */
    public abstract void onFailure(String responseresult);
}

第四步:看下我们重量级别的okhttputils

package cn.yuan.yu.library.utils;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import cn.yuan.yu.library.OkHttpUtilsConfig;
import cn.yuan.yu.library.ProgressResponseBody;
import cn.yuan.yu.library.R;
import cn.yuan.yu.library.bean.RequestPacket;
import cn.yuan.yu.library.listener.DonwloadResponseListener;
import cn.yuan.yu.library.listener.ResponseListener;


/**
 * Created by yukuo on 2016/3/18.
 * 这是一个okhttp请求的工具类
 */
public class OkHttpUtil {
    private static final OkHttpClient mOkHttpClient = new OkHttpClient();
    //请求类型
    public static final MediaType mJSON = MediaType.parse("application/json; charset=utf-8");
    //请求编码格式
    private static final String CHARSET_NAME = "UTF-8";


    static {
        mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
    }

    /**
     * 这是一个get请求拼接请求路径的方法
     *
     * @param requestPacket 请求参数
     * @return
     */
    public static String appendUrl(RequestPacket requestPacket) {
        return requestPacket.url + "?" + appendArguments(requestPacket);
    }

    /**
     * 这是一个拼接get请求请求参数的方法
     *
     * @param requestPacket 请求参数
     * @return
     */
    public static String appendArguments(RequestPacket requestPacket) {
        String argument = "";
        for (String key : requestPacket.arguments.keySet()) {
            if (requestPacket.getArgument(key) != null) {
                if (argument.equals("")) {
                    argument = key + "=" + requestPacket.getArgument(key);
                } else {
                    argument = argument + "&" + key + "=" + requestPacket.getArgument(key);
                }
            }
        }
        return argument;
    }

    /**
     * 这是一个请求的网络的方法
     *
     * @param method        请求方式
     * @param requestPacket 参数实体
     * @param listener      回调
     */
    public static void Request(int method, RequestPacket requestPacket, final ResponseListener listener) {
        Request request = null;
        Request.Builder builder = new Request.Builder();
        //设置请求类型
        builder.header("Content-Type", "application/json");
        // 添加头信息
        for (String key : requestPacket.headers.keySet()) {
            if (requestPacket.getHeader(key) != null) {
                builder.header(key, requestPacket.headers.get(key));
            }
        }
        //设置请求的url
        if (method == RequestPacket.POST) {
            //如果是post请求
            if (OkHttpUtilsConfig.getInstance().isPostJson()) {
                RequestBody body = RequestBody.create(mJSON, new Gson().toJson(requestPacket.arguments));
                request = new Request.Builder()
                        .url(requestPacket.url)
                        .post(body)
                        .build();
            } else {
                FormEncodingBuilder builer = new FormEncodingBuilder();
                Set<String> keysets = requestPacket.arguments.keySet();
                for (String key : keysets) {
                    builer.add(key, requestPacket.arguments.get(key).toString());
                }
                request = new Request.Builder()
                        .url(requestPacket.url)
                        .post(builer.build())
                        .build();
            }

        } else if (method == RequestPacket.GET) {
            String url = appendUrl(requestPacket);
            //如果是get请求
            request = builder.url(url).build();
        }
        L.i("请求路径和参数", request.toString() + new Gson().toJson(requestPacket.arguments));
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException e) {
                sendFaliure("", listener, e);
            }

            @Override
            public void onResponse(final Response response) throws IOException {
                final String result = response.body().string();
                JsonObject re = new Gson().toJsonTree(result).getAsJsonObject();
                if (re.get(OkHttpUtilsConfig.getInstance().getResultCodeKey()).equals(OkHttpUtilsConfig.getInstance().getResultCodeValue())) {
                    SendSuccess(result, listener);
                } else {
                    String responseresult = re.get(OkHttpUtilsConfig.getInstance().getResultMsgKey()).getAsString();
                    sendFaliure(responseresult, listener, null);
                }
            }
        });
    }

    /**
     * 发送成功回到
     *
     * @param result   返回的结果
     * @param listener 回调监听
     */
    private static void SendSuccess(final String result, final ResponseListener listener) {
        OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
            @Override
            public void run() {
                /**
                 * 获取要转换的json类型
                 */
                Type genType = listener.getClass().getGenericSuperclass();
                Class clzss = (Class) ((ParameterizedType) genType).getActualTypeArguments()[0];
                try {
                    L.i("返回的结果", result);
                    listener.onSuccess(new Gson().fromJson(result, clzss));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 发送失败的消息
     *
     * @param responseresult 返回的错误信息
     * @param listener       回调监听
     * @param e              异常
     */
    private static void sendFaliure(final String responseresult, final ResponseListener listener, final IOException e) {
        OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
            @Override
            public void run() {
                listener.onFailure(responseresult);
                if (e instanceof SocketTimeoutException) {
                    T.showLong(OkHttpUtilsConfig.getInstance().getContext(), R.string.net_error);
                    return;
                } else if (e instanceof ConnectException) {
                    T.showLong(OkHttpUtilsConfig.getInstance().getContext(), R.string.net_null);
                    return;
                }
            }
        });
    }

    /**
     * 这是一个下载文件的方法
     *
     * @param donwloadurl              下载路径
     * @param filepath                 文件路径
     * @param filename                 文件名字
     * @param donwloadResponseListener 回调监听
     */
    public static void donwloadFile(String donwloadurl, final String filepath, final String filename, final DonwloadResponseListener donwloadResponseListener) {

        //添加拦截器,自定义ResponseBody,添加下载进度
        mOkHttpClient.networkInterceptors().add(new Interceptor() {
            @Override
            public Response intercept(Chain chain) {
                Response originalResponse = null;
                try {
                    originalResponse = chain.proceed(chain.request());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return originalResponse.newBuilder().body(
                        new ProgressResponseBody(originalResponse.body(), donwloadResponseListener))
                        .build();
            }
        });
        //封装请求
        Request request = new Request.Builder()
                //下载地址
                .url(donwloadurl)
                .build();
        //发送异步请求
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                /**
                 * 失败回调监听
                 */
                OkHttpUtilsConfig.getInstance().getMainHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        donwloadResponseListener.onfailure();
                    }
                });
            }

            @Override
            public void onResponse(Response response) throws IOException {
                //将返回结果转化为流,并写入文件
                int len;
                byte[] buf = new byte[2048];
                InputStream inputStream = response.body().byteStream();
                //可以在这里自定义路径

                File file1 = new File(filepath + filename);
                FileOutputStream fileOutputStream = new FileOutputStream(file1);

                while ((len = inputStream.read(buf)) != -1) {
                    fileOutputStream.write(buf, 0, len);
                }

                fileOutputStream.flush();
                fileOutputStream.close();
                inputStream.close();
            }
        });
    }


}

第五步:我们封装的下载文件相关类

下载回调
package cn.yuan.yu.library.listener;

/**
 * Created by yukoyuan on 16/7/10.
 * 这是一个下载文件的回调监听
 */
public interface DonwloadResponseListener {
    /**
     * @param bytesRead     已下载字节数
     * @param contentLength 总字节数
     * @param done          是否下载完成
     * @deprecated 计算方式是 (100 * bytesRead) / contentLength
     * 日志为 45%...
     */
    void OnSuccess(long bytesRead, long contentLength, boolean done);

    /**
     * 下载失败的回调方法
     */
    void onfailure();
}
其他代码和工具类
package cn.yuan.yu.library;

import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.ResponseBody;

import java.io.IOException;

import cn.yuan.yu.library.listener.DonwloadResponseListener;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

/**
 * Created by yukoyuan on 16/7/10.
 * 这是一个下载文件实体的封装
 */
public class ProgressResponseBody extends ResponseBody {
    private final ResponseBody responseBody;
    private final DonwloadResponseListener progressListener;
    private BufferedSource bufferedSource;

    public ProgressResponseBody(ResponseBody responseBody, DonwloadResponseListener progressListener) {
        this.responseBody = responseBody;
        this.progressListener = progressListener;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }


    @Override
    public long contentLength() throws IOException {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() throws IOException {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source source(Source source) {
        return new ForwardingSource(source) {
            long totalBytesRead = 0L;

            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                progressListener.OnSuccess(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
                return bytesRead;
            }
        };
    }

}
日志类和Toast类
package cn.yuan.yu.library.utils;

import android.util.Log;

import cn.yuan.yu.library.OkHttpUtilsConfig;


/**
 * Created by yukuo on 2015/11/18.
 * 这是一个log的工具类
 */
public class L {
    private static boolean flag = OkHttpUtilsConfig.getInstance().isShowLog();

    public static void e(String tag, String text) {
        if (flag) {
            Log.e(tag, text);
        }
    }

    public static void d(String tag, String text) {
        if (flag) {
            Log.d(tag, text);
        }
    }

    public static void i(String tag, String text) {
        if (flag) {
            Log.i(tag, text);
        }
    }

    public static void v(String tag, String text) {
        if (flag) {
            Log.v(tag, text);
        }
    }

    public static void w(String tag, String text) {
        if (flag) {
            Log.w(tag, text);
        }
    }

    public static void wtf(String tag, String text) {
        if (flag) {
            Log.wtf(tag, text);
        }
    }
}
package cn.yuan.yu.library.utils;

import android.content.Context;
import android.widget.Toast;

/**
 * Created by yukuo on 2016/1/9.
 * 这是一个toast的工具类
 */
public class T {
    public static boolean isShow = true;

    /**
     * 短时间显示Toast类型为CharSequence的数据
     *
     * @param context
     * @param message
     */
    public static void showShort(Context context, CharSequence message) {
        if (isShow)
            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    }

    /**
     * 短时间显示Toast类型为int的数据
     *
     * @param context
     * @param message
     */
    public static void showShort(Context context, int message) {
        if (isShow)
            Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    }

    /**
     * 长时间显示Toast类型为CharSequence的数据
     *
     * @param context
     * @param message
     */
    public static void showLong(Context context, CharSequence message) {
        if (isShow)
            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
    }

    /**
     * 长时间显示Toast类型为int的数据
     *
     * @param context
     * @param message
     */
    public static void showLong(Context context, int message) {
        if (isShow)
            Toast.makeText(context, message, Toast.LENGTH_LONG).show();
    }

    /**
     * 自定义显示Toast时间类型为CharSequence的数据
     *
     * @param context
     * @param message
     * @param duration
     */
    public static void show(Context context, CharSequence message, int duration) {
        if (isShow)
            Toast.makeText(context, message, duration).show();
    }

    /**
     * 自定义显示Toast时间类型为int的数据
     *
     * @param context
     * @param message
     * @param duration
     */
    public static void show(Context context, int message, int duration) {
        if (isShow)
            Toast.makeText(context, message, duration).show();
    }
}

至此我们工具类封装完成了,看一下代码,并没有多少,有没有感觉很简单啊,没那么复杂,有什么问题,欢迎留言给我,也欢迎给我star,谢谢思密达们

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
对于使用OkHttp进行封装,以下是一个基本的示例: 1. 首先,确保已经在项目中添加了OkHttp的依赖。在build.gradle文件中添加以下代码: ```groovy implementation 'com.squareup.okhttp3:okhttp:4.9.0' ``` 2. 创建一个HttpHelper类来封装OkHttp使用。示例代码如下: ```java import okhttp3.*; import java.io.IOException; public class HttpHelper { private final OkHttpClient client; public HttpHelper() { client = new OkHttpClient(); } public void get(String url, Callback callback) { Request request = new Request.Builder() .url(url) .build(); client.newCall(request).enqueue(callback); } public void post(String url, RequestBody requestBody, Callback callback) { Request request = new Request.Builder() .url(url) .post(requestBody) .build(); client.newCall(request).enqueue(callback); } } ``` 3. 现在可以在其他类中使用HttpHelper进行网络请求。以下是一个使用GET请求的示例: ```java import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; import java.io.IOException; public class Main { public static void main(String[] args) { HttpHelper httpHelper = new HttpHelper(); String url = "https://api.example.com/data"; httpHelper.get(url, new Callback() { @Override public void onFailure(Call call, IOException e) { // 处理请求失败的情况 } @Override public void onResponse(Call call, Response response) throws IOException { // 处理请求成功的情况 String responseData = response.body().string(); System.out.println(responseData); } }); } } ``` 以上示例中,我们首先创建了一个HttpHelper实例,然后使用get方法发送GET请求。在回调函数中,可以处理请求成功或失败的情况,并处理返回的响应数据。 对于POST请求,可以使用post方法,并传递一个RequestBody对象作为请求体。具体的请求参数和请求头信息可以根据实际需求进行设置。 这只是一个基本的封装示例,你可以根据自己的项目需求进行更多的定制和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值