手记

Okhttp3的封装 搞定常用的请求

开篇

这篇博客写下Okhttp的封装,作为安卓最应用最广泛的网络请求框架,okhttp也是被玩出了各种姿势,虽然已经帮我们把一个原生的网络请求封装精简了很多,不过为了更加的方便,还是再进行一层的封装,这里的封装包括了常用的GET,POST,DELETE,PUT的请求,其中post包括了基于json格式的请求,以及表单形式的请求,因为上传文件基本都是用的表单去提交的,基本这一套封装可以搞定安卓应用里面一般的网络请求了。

具体封装

首先看看全部的文件

包括了3个接口文件,和3个实现类文件。

接口文件

请求参数的接口

public interface IRequest {
    public static final String POST = "POST";
    public static final String GET = "GET";
    public static final String DELETE = "DELETE";
    public static final String PUT = "PUT";

    /**
     *  请求方式
     * @param method
     */
    void setMethod(String method);

    /**
     *  指定请求头
     * @param key
     * @param value
     */
    void setHeader(String key, String value);

    /**
     *  指定请求信息
     * @param key
     * @param value
     */
    void setBody(String key, Object value);

    /**
     * 提供给执行库请求行URL
     * @return
     */
    String getUrl();

    /**
     * 提供给执行库请求行URL
     * @return
     */
    Map<String,String> getHeader();

    /**
     *  请求体
     * @return
     */
    String getBody();

}

方法具体的作用 注释都写得很清楚了,接下来

请求响应接口

public interface IResponse {

    /**
     *  响应码
     * @return
     */
    int getCode();

    /**
     *  返回的数据
     * @return
     */
    String getData();
}

请求方法接口

public interface IHttpClient {

    IResponse get(IRequest request);

    /**
     *  json格式的post
     * @param request
     * @return
     */
    IResponse post(IRequest request);

    /**
     *  表单类型的post
     * @param request
     * @param map
     * @param file
     * @return
     */
    IResponse upload_image_post(IRequest request, Map<String, Object> map, File file);
    IResponse delete(IRequest request);
    IResponse put(IRequest request);
}

这里就用的图片上传,其它文件上传也只是改一下文件类型一样。需要注意的是,这里的上传图片的post方法传入的参数是使用了一个map类型的键值对。
然后就是具体的实现类了

实现类

请求参数实现类

**
 * @author Legend
 * @data by on 2017/11/23.
 * @description
 */

public class RequestImpl implements IRequest {

    private String method = POST;
    private String url;
    private Map<String,String> header;
    private Map<String,Object> body;

    public RequestImpl(String url) {
        /**
         *  初始化公共参数和头部信息
         */
        this.url = url;
        header = new HashMap();
        body = new HashMap<>();
    }
    @Override
    public void setMethod(String method) {
        this.method = method;
    }

    @Override
    public void setHeader(String key, String value) {
        header.put(key,value);
    }

    @Override
    public void setBody(String key, Object value) {
        body.put(key,value);
    }

    @Override
    public String getUrl() {
        if (GET.equals(method)) {
            // 组装post请求参数
            for (String key : body.keySet()) {
                url = url.replace("${"+key+"}",body.get(key).toString());
            }
        }
        return url;
    }

    @Override
    public Map<String, String> getHeader() {
        return header;
    }

    @Override
    public String getBody() {
        // 组装post请求参数
        if (body != null) {
            return new Gson().toJson(this.body,HashMap.class);
        } else {
            return "{}";
        }
    }
}

这里用到了Gson来组装post请求的参数。

响应接口实现类

**
 * @author Legend
 * @data by on 2017/11/23.
 * @description
 */

public class ResponseImpl implements IResponse {
    public static final int STATE_UNKNOW_ERROR = 100001;
    public static int STATE_OK = 200;
    private int code;
    private String data;

    @Override
    public String getData() {
        return data;
    }
    @Override
    public int getCode () {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public void setData(String data) {
        this.data = data;
    }

}

这里没什么好说的,最后是重点了

请求方法实现类

/**
 * @author Legend
 * @data by on 2017/11/23.
 * @description
 */

public class OkHttpClientImpl implements IHttpClient {
    OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
            .build();

    @Override
    public IResponse get(IRequest request) {
        /**
         *  解析业务参数
         */
        // 指定请求方式
        request.setMethod(IRequest.GET);
        Map<String,String> header = request.getHeader();
        Request.Builder builder = new Request.Builder();
        for (String key : header.keySet()) {
            builder.header(key,header.get(key));
        }
        builder.url(request.getUrl()
        ).get();
        Request okRequest = builder.build();
        return execute(okRequest);
    }

    @Override
    public IResponse post(IRequest request) {
        request.setMethod(IRequest.POST);
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(mediaType,request.getBody().toString());

        Map<String,String> header = request.getHeader();
        Request.Builder builder = new Request.Builder();
        for (String key : header.keySet()) {
            builder.header(key,header.get(key));
        }
        builder.url(request.getUrl())
                .post(requestBody);
        Request okRequest = builder.build();
        return execute(okRequest);
    }

    @Override
    public IResponse upload_image_post(IRequest request,Map<String,Object> map,File file) {
        /**
         *  实现文件上传
         */
        request.setMethod(IRequest.POST);
        MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");
        MultipartBody.Builder requestBody = new MultipartBody
                .Builder().setType(MultipartBody.FORM);
        if (file != null) {
            requestBody.addFormDataPart("image",file.getName(),
                    RequestBody.create(MEDIA_TYPE_IMAGE,file));
        }
        if (map != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry entry : map.entrySet()) {
                requestBody.addFormDataPart(valueOf(entry.getKey()), valueOf(entry.getValue()));
            }
        }
        Map<String,String> header = request.getHeader();
        Request.Builder builder = new Request.Builder();
        for (String key : header.keySet()) {
            builder.header(key,header.get(key));
        }
        builder.url(request.getUrl())
                .post(requestBody.build());
        Request okRequest = builder.build();
        return execute(okRequest);
    }

    @Override
    public IResponse delete(IRequest request) {
        request.setMethod(IRequest.DELETE);
        Map<String,String> header = request.getHeader();
        Request.Builder builder = new Request.Builder();
        for (String key : header.keySet()) {
            builder.header(key,header.get(key));
        }
        builder.url(request.getUrl())
                .delete(null);
        Request okRequest = builder.build();
        return execute(okRequest);
    }

    @Override
    public IResponse put(IRequest request) {
        request.setMethod(IRequest.PUT);
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(mediaType,request.getBody().toString());

        Map<String,String> header = request.getHeader();
        Request.Builder builder = new Request.Builder();
        for (String key : header.keySet()) {
            builder.header(key,header.get(key));
        }
        builder.url(request.getUrl())
                .put(requestBody);
        Request okRequest = builder.build();
        return execute(okRequest);
    }

    private IResponse execute(Request request) {
        ResponseImpl commonResponse = new ResponseImpl();
        try {
            Response response = mOkHttpClient.newCall(request).execute();
            // 设置状态码
            commonResponse.setCode(response.code());
            String body = response.body().string();
            // 设置响应数据
            commonResponse.setData(body);
        } catch (IOException e) {
            e.printStackTrace();
            commonResponse.setCode(ResponseImpl.STATE_UNKNOW_ERROR);
            commonResponse.setData(e.getMessage());
        }
        return commonResponse;
    }
}

每个请求方法把参数准备好后都是放到execute方法去执行,最后我们可以通过返回的commonResposne拿到响应码和服务器端返回的数据。

使用方法

使用起来还是比较方便的,看看基本的使用,如下

IRequest request = new RequestImpl(这里传入url);
//设置请求头,这里要几个就setHeader几次
request.setHeader(key,value);
// 设置请求体 同上
request.setBody(key,value);
// 获取一个okhttpclient实例
IHttpClient mHttpClient = new OkHttpClientImpl();
// 得到服务器端返回的结果
IResponse response = mHttpClient.get(request);

得到返回结果,就可以做我们想要的操作了,可以写一个回调把请求结果传入进行,用handler向主线程发送响应结果,这里就不多说了。
然后是表单类型的请求,可以用一个Map来组装请求参数,然后直接传入方法即可,不需要上传文件的话就可以直接传null。

总结

合理的封装除了能让我们的项目的业务逻辑看起来更加清晰,还能锻炼面向对象的思维,多折腾下总没错,就先到这里了。

8人推荐
随时随地看视频
慕课网APP