仿Retrofit框架的实现--LQHttpRetrofit(二)

本篇就开始对LQHttpRetrofit是如何实现的解析---更多的是去看代码注释解析

本篇只是带着过一下,具体工程已上传到gitlib,gitlab地址在本篇末尾有链接

先看项目的基本目录接口(旨在解析Retrofit的实现思路,所以只实现了一个基本的)

首先看LqRetrofit类的实现解析:

 

看代码

public class LQRetrofit {

    //缓存MethodAnnotationInfo容器
    private final ConcurrentHashMap<String, MethodAnnotationInfo> methodAnnotationInfoCache = new ConcurrentHashMap<>();

    //实现真正的网络请求的适配器
    private LQHttpAdapter lqHttpAdapter;
    //配置的基本url地址
    private String baseUrl;

    private LQRetrofit(Builder builder) {
        this.lqHttpAdapter = builder.getLQHttpAdapter();
        this.baseUrl = builder.getBaseUrl();
    }

    public String getBaseUrl() {
        return baseUrl;
    }

    public <T> T create(Class<T> service) {
        //验证service是否是接口 且接口中要有方法
        Util.validateServiceInterface(service);
        //使用动态代理
        ClassLoader classLoader = service.getClassLoader();
        Class[] classes = {service};
        InvocationHandler invocationHandler = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //如果是在Object类中声明的方法(也就是自己实现了),就直接调用
                if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(proxy, args);
                } else if (method.isDefault()) { //如果是接口中定义的默认方法 抛出异常
                    return Util.invokeDefaultMethod(method, service, proxy, args);
                } else { //开始实现LQRetrofit
                    //获取方法返回值的全类名
                    Type genericReturnType = method.getGenericReturnType();
                    // 判断返回值的类型是否是参数化类型
                    if (genericReturnType instanceof ParameterizedType) {
                        //获取MethodAnnotationInfo 先从缓存中拿,没拿到就去解析再获取
                        MethodAnnotationInfo methodAnnotationInfo = getMethodAnnotationInfo(method, args, genericReturnType);
                        //返回Call结果值
                        return new Call<>(lqHttpAdapter, methodAnnotationInfo);
                    } else {
                        throw new IllegalStateException("The return value type of the method must be the Call<T> type");
                    }
                }
            }
        };
        return (T) Proxy.newProxyInstance(classLoader, classes, invocationHandler);
    }

    /**
     * 获取解析后的MethodAnnotationInfo
     *
     * @param method 方法
     * @param args   方法参数
     * @param genericReturnType   接口返回值类型
     * @return
     */
    public MethodAnnotationInfo getMethodAnnotationInfo(Method method, Object[] args, Type genericReturnType) {
        String methodName = method.getName();
        MethodAnnotationInfo annotationInfo = methodAnnotationInfoCache.get(methodName);
        if (annotationInfo != null) {
            return annotationInfo;
        } else {
            MethodAnnotationInfo methodAnnotationInfo = parseMethodAnnotationInfo(method, args, genericReturnType);
            methodAnnotationInfoCache.put(methodName, methodAnnotationInfo);
            return methodAnnotationInfo;
        }
    }

    /**
     * 解析接口方法中的注解
     *
     * @param method 方法
     * @param args   方法参数
     * @return
     */
    public MethodAnnotationInfo parseMethodAnnotationInfo(Method method, Object[] args, Type genericReturnType) {
        //获取调用接口方法上的所有注解
        Annotation[] methodAnnotations = method.getAnnotations();
        //解析方法上的所有注解
        if (methodAnnotations.length < 1) {
            throw new IllegalStateException("Please specify @GET or @POST or @PUT or @DELETE");
        }
        ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
        Type[] typeArguments = parameterizedType.getActualTypeArguments();// 返回表示此类型实际类型参数的 Type 对象的数组
        Type resultType = typeArguments[0];//接口获取返回值的类型
        //实例化MethodAnnotationInfo
        MethodAnnotationInfo annotationInfo = new MethodAnnotationInfo();
        annotationInfo.setResultType(resultType);
        for (Annotation annotation : methodAnnotations) {
            if (annotation instanceof GET) {
                annotationInfo.setRequestType(RequestType.GET);
                String url = ((GET) annotation).value();
                if (((GET) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof POST) {
                annotationInfo.setRequestType(RequestType.POST);
                String url = ((POST) annotation).value();
                if (((POST) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof DELETE) {
                annotationInfo.setRequestType(RequestType.DELETE);
                String url = ((DELETE) annotation).value();
                if (((DELETE) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof PUT) {
                annotationInfo.setRequestType(RequestType.PUT);
                String url = ((PUT) annotation).value();
                if (((PUT) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof PATCH) {
                annotationInfo.setRequestType(RequestType.PATCH);
                String url = ((PATCH) annotation).value();
                if (((PATCH) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof HEAD) {
                annotationInfo.setRequestType(RequestType.HEAD);
                String url = ((HEAD) annotation).value();
                if (((HEAD) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof OPTIONS) {
                annotationInfo.setRequestType(RequestType.OPTIONS);
                String url = ((OPTIONS) annotation).value();
                if (((OPTIONS) annotation).useBaseUrl()) {
                    url = getBaseUrl() + url;
                }
                annotationInfo.setUrl(url);
            } else if (annotation instanceof Headers) {
                String[] headers = ((Headers) annotation).value();
                if (headers.length > 0) {
                    for (String header : headers) {
                        String[] split = header.split(":");
                        if (split.length != 2) {
                            throw new IllegalArgumentException("Designated header is not standard");
                        } else {
                            annotationInfo.addHeader(split[0], split[1]);
                        }
                    }
                } else {
                    throw new NullPointerException("Headers is not null");
                }
            }
        }
        //解析方法中的参数注解
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        if (parameterAnnotations.length > 0) {
            for (int i = 0; i < parameterAnnotations.length; i++) {
                Annotation[] parameterAnnotation = parameterAnnotations[i];
                Annotation annotation = parameterAnnotation[0];
                if (annotation instanceof Header) {
                    String key = ((Header) annotation).value();
                    annotationInfo.addHeader(key, args[i] + "");
                } else if (annotation instanceof Body) {
                    annotationInfo.setBody(args[i] + "");
                } else if (annotation instanceof Param) {
                    String key = ((Param) annotation).value();
                    annotationInfo.addParam(key, args[i] + "");
                } else if (annotation instanceof PathVariable) {
                    annotationInfo.addPath(new KVEntry<>(((PathVariable) annotation).value(),
                            args[i] + ""));
                }
            }
        }
        return annotationInfo;
    }

    public static class Builder {

        private String baseUrl = "";
        private LQHttpAdapter lqHttpAdapter;

        public Builder(LQHttpAdapter lqHttpAdapter) {
            this.lqHttpAdapter = lqHttpAdapter;
        }

        String getBaseUrl() {
            return baseUrl;
        }

        public Builder setBaseUrl(String baseUrl) {
            this.baseUrl = Util.strIsEmpty(baseUrl) ? "" : baseUrl;
            return this;
        }

        LQHttpAdapter getLQHttpAdapter() {
            return lqHttpAdapter;
        }

        public LQRetrofit build() {
            return new LQRetrofit(this);
        }
    }

}

看MethodAnnotationInfo类:

/**
 * 最终请求的信息(也就是注解信息)
 */
public class MethodAnnotationInfo implements Serializable {

    private static final long serialVersionUID = 1L;

    //请求方式
    private String requestType;
    //请求url地址
    private String url;
    //添加请求头
    private LinkedHashMap<String, String> headers;
    //添加请求体
    private String body;
    //请求参数
    private Map<String, String> params;
    //返回值类型
    private Type resultType;
    //组拼的url路径
    private LinkedList<KVEntry<String, String>> paths;

    public Type getResultType() {
        return resultType;
    }

    void setResultType(Type resultType) {
        this.resultType = resultType;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    void addHeader(String key, String value) {
        if (headers == null) {
            headers = new LinkedHashMap<>();
        }
        this.headers.put(key, value);
    }

    void addParam(String key, String value) {
        if (params == null) {
            params = new HashMap<>();
        }
        this.params.put(key, value);
    }

    public Map<String, String> getParams() {
        return params;
    }

    public String getBody() {
        return body;
    }

    void setBody(String body) {
        this.body = body;
    }

    public String getRequestType() {
        return requestType;
    }

    void setRequestType(String requestType) {
        this.requestType = requestType;
    }

    public String getUrl() {
        return parseUrl(this.url,this.paths);
    }

    void setUrl(String url) {
        this.url = url;
    }

    LinkedList<KVEntry<String, String>> getPaths() {
        return paths;
    }

    void addPath(KVEntry<String, String> KVEntry) {
        if (paths==null){
            paths = new LinkedList<>();
        }
        paths.add(KVEntry);
    }

    @Override
    public String toString() {
        return "MethodAnnotationInfo{" +
                "requestType='" + requestType + '\'' +
                ", url='" + url + '\'' +
                ", headers=" + headers +
                ", params=" + params +
                ", body='" + body + '\'' +
                '}';
    }

    /**
     * 解析url--得到真正的url
     *
     * @return 解析后的url
     */
    private String parseUrl(String url,LinkedList<KVEntry<String, String>> paths) {
        if (paths != null && paths.size() > 0 && url.contains("{") && url.contains("}")) {
            return checkUrl(url, paths);
        } else {
            return url;
        }
    }

    /**
     * 检查设置的url中是否还存在@Path中设置的路径
     * @param newUrl  原url
     * @param parameterEntries @Path中设置的路径
     * @return 返回实际的url
     */
    private String checkUrl(String newUrl, LinkedList<KVEntry<String, String>> parameterEntries) {
        if (parameterEntries.size() <= 0) {
            return newUrl;
        }
        KVEntry<String, String> KVEntry = parameterEntries.removeLast();
        String key = KVEntry.getKey();
        if (newUrl.contains(key)) {
            String replace = newUrl.replace("{" + key + "}", KVEntry.getValue());
            return checkUrl(replace, parameterEntries);
        }
        return newUrl;
    }
}

看网络请求接口返回结果集的包装类:Call类

/**
 * 接口返回值的包装类(也是真正执行类)
 * @param <R>
 */
public class Call<R> {

    private LQHttpAdapter lqHttpAdapter;
    private MethodAnnotationInfo methodAnnotationInfo;


    Call(LQHttpAdapter lqHttpAdapter, MethodAnnotationInfo methodAnnotationInfo) {
        this.lqHttpAdapter = lqHttpAdapter;
        this.methodAnnotationInfo = methodAnnotationInfo;
    }


    public void execute(CallBack<R> callBack) {
        lqHttpAdapter.httpRequest(methodAnnotationInfo, callBack);
    }

}

看LQHttpAdapter接口类:

/**
 * 网络框架适配器 用于集成其它网络框架
 */
public interface LQHttpAdapter {

    void httpRequest(MethodAnnotationInfo annotationInfo,CallBack callBack);

}

看CallBack类:

/**
 * 执行的网络请求后的回调
 * @param <R>
 */
public abstract class CallBack<R> {

    public abstract void success(R r);

    public abstract void fail(String e);

    /**
     * 进度回调
     *
     * @param progress
     * @param total
     */
    public void onProgress(int progress, long total) {

    }
}

以上基本就是LqRetrofit实现的一些核心类;

最后就上一篇演示的测试demo中的OkHttpAdapter类,也就是如何去集成或自定义扩展:

/**
 * 集成LQRetrofit的适配器:对OkHttp网络框架的适配器 的demo
 */
public class OkHttpAdapter implements LQHttpAdapter {

    private static final OkHttpClient okHttpClient;
    private static final Gson gson;

    static {
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .build();
        gson = new Gson();
    }

    @Override
    public void httpRequest(MethodAnnotationInfo annotationInfo, CallBack callBack) {
        Request.Builder builder = new Request.Builder().url(annotationInfo.getUrl());
        switch (annotationInfo.getRequestType()) {
            case RequestType.GET:
                Map<String, String> headers = annotationInfo.getHeaders();
                builder.get();
                if (headers != null && headers.size() > 0) {
                    builder.headers(Headers.of(headers));
                }
                executeCallback(builder.build(), callBack, annotationInfo);
                break;
            case RequestType.POST:
                //执行了okhttp的post请求...........
                Request request = null;
                FormBody.Builder formBodyBuilder = new FormBody.Builder();
                Map<String, String> params = annotationInfo.getParams();
                String body = annotationInfo.getBody();
                if (params != null && body != null && body.length() > 0) {
                    throw new IllegalStateException("params and body can only exist one");
                }
                if (params != null && params.size() > 0) {
                    params.forEach(formBodyBuilder::add);
                    request = builder.post(formBodyBuilder.build()).build();
                }
                if (body != null && body.length() > 0) {
                    request = builder.post(RequestBody.create(MediaType.parse("application/json"), body)).build();
                }
                if (request == null) {
                    throw new IllegalStateException("params and body must specify one");
                }
                executeCallback(request, callBack, annotationInfo);
                break;
            case RequestType.PUT:
                //执行了okhttp的put请求...........
                break;
            case RequestType.DELETE:
                //执行了okhttp的delete请求...........
                break;
            case RequestType.PATCH:
                //执行了okhttp的patch请求...........
                break;
            case RequestType.HEAD:
                //执行了okhttp的head请求...........
                break;
            case RequestType.OPTIONS:
                //执行了okhttp的options请求...........
                break;
            default:
                break;
        }
    }

    private void executeCallback(Request request, CallBack callBack, MethodAnnotationInfo annotationInfo) {
        okHttpClient.newCall(request)
                .enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        callBack.fail(e.toString());
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        ResponseBody body = response.body();
                        if (body != null) {
                            String json = body.string();
                            callBack.success(gson.fromJson(json, annotationInfo.getResultType()));
                            body.close();
                        } else {
                            callBack.fail("body is null");
                        }
                    }
                });
    }


}

所有代码已上传到了gitLib,可以根据代码中的注释去理解

《LqHttpRetrofit工程代码》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值