OkHttp的封装和使用详解

来源:互联网 发布:雅马哈摩托 知乎 编辑:程序博客网 时间:2024/05/19 13:19

其实一直想写这篇文章的,为什么不写呢?因为不想写,不要咬我.我要开始装逼了.接触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 0
原创粉丝点击