okhttp二次封装+动态代理

概述

本文中升级http基于前章中整理的网络通信组件,其实在实际开发中我们网络请求非常麻烦,如果高效有质量通信,非常重要,而这次我要介绍的如果加入动态代理和注解技术。当前版本3.0.github地址:

https://github.com/apple317/HttpClientUtils 

目前支持

  • 支持动态代理
  • 支持注解技术
  • 一般的get请求
  • 一般的post请求 支持文本、表单、表单文件、单个文件操作 支持
  • 基于Http Post的文件上传(类似表单) 支持
  • 文件上传进度  支持
  • 下载文件进度 支持
  • 支持url关闭网络请求 支持
  • 支持session的保持 支持
  • 支持取消某个请求 支持
  • 支持数据异步刷新操作 
  • 支持取消tag请求、支持url取消请求  支持
  • 支持HEAD  支持
  • 支持自签名网站https的访问,提供方法设置下证书就行 不支持
  • DELETE、PATCH、PUT 支持
  • 加入网络配置、请求过程抽离 支持
  • 加入gson解析,建议加入插件gsonformat来生成解析对象,传入解析类方法setParse
  • 加入url表识来区分请求  支持

动态代理技术

      其他对象提供一种代理以控制对这个对象的访问,当我们用http访问请求时,如果每次都去申请同样请求方式、请求方法、请求参数等,这时候就需要一个同一接口来定义统一实现,这样方便维护更好扩展,当然这时候光用动态代理,只能统一接口实现,哪请求传入哪些,如果全手动去代入也不够方便,这时候加入注解注入技术+动态代理技术+注解缓冲,更好达到Retrofit技术。
 
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos();
repos.enqueue(new Callback<List<Repo>>(){
    @Override
    public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response){

    }

    @Override
    public void onFailure(Call<List<Repo>> call, Throwable t){

    }
});
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

上面看到这个create方法:

    动态代理返回范型类对象,其实最重要代码首先使用Proxy,他作用就是当你传入接口类,当调用者调用其中方法,Proxy就是会调用4步操作:
   1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
   2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
        Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
   3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
        Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
   4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
        Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
        为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))。

而当调用到invoke方法时候:

proxy:代理类对象
method:调用方法
args:方法传入数值。

注解注入参数:

        ServiceMethod serviceMethod = loadServiceMethod(method);此类中全是获取注解的类。  

缓冲注解参数: 

      下面方法看到serviceMethodCache变量,其实就是Map类型,通过method存下所有注解方式数值,这样第二次调用直接调用map中。

 ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

以上全部就是retrofit技术要点。

升级版本

      例子:    

看到定义http接口,这样可以统一把http放到一起,默认请求post_FORM,可以不用传,解析类必须传,如果么有解析类,也可以不用传。httpBaseUrl是注解传入接口域名前缀地址。
 public interface LoginApiStores {
        @HttpMehod(METHOD.POST_FORM)
        @HttpParse(BaseBean.class)
        @HttpBaseUrl("https://api.hushaoping.com/v2/")
        void getHomePageData(@FieldParam BaseParams baseParams);
    }
    /**
     * 首页菜单
     */
    public void getHomepageQuickEntryList(HttpCallback httpClick) {
        AppBaseParams appBaseParams = new AppBaseParams();
        appBaseParams.put("app_version_id", "234");
        appBaseParams.put("app_market_id", "23");
        appBaseParams.put("app_platform_id", "1");
        appBaseParams.put("user_id", "");
        BaseHttpClient.newBuilder().urlIdentifier("getHomePageData").build().execute(LoginApiStores.class,
                new HttpCallback() {
                    @Override
                    public void success(String content, BaseHttpClient client, Object parse) {
                        BaseBean bean=(BaseBean)parse;
                        Log.e("HU","content======content==="+bean.getRetCode());

                    }

                    @Override
                    public void error(Throwable error, BaseHttpClient client) {

                    }
                }
        ).getHomePageData(appBaseParams.signParams());
    }

Api介绍

        HttpMethod:传入请求方式post/get等.
        HttpParse:传入请求解析类.
        HttpBaseUrl:传入请求url地址。
        urlIdentifier:请求返回唯一标识.

源码

     
/**
     * 注解方式
     * 反射
     *
     * @param service
     * @param click
     * @param <T>
     * @return
     */
    public <T> T execute(final Class<T> service, final BaseCallback click) {
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object... args)
                            throws Throwable {
                        // If the method is a method from Object then defer to normal invocation.
                        if (args.length > 0) {
                            BaseParams params = (BaseParams) args[0];
                            loadServiceMethod(click, method, params);
                        }
                        return proxy;
                    }
                });
    }

    /**
     * @param click
     * @param method
     * @param baseParams
     */
    public void loadServiceMethod(BaseCallback click, Method method, BaseParams baseParams) {
        BaseHttpClient baseHttpClient;
        synchronized (serviceMethodCache) {
            baseHttpClient = serviceMethodCache.get(method);
            if (baseHttpClient == null) {
                for (Annotation annotation : method.getAnnotations()) {
                    if (annotation instanceof HttpMehod) {
                        this.method = ((HttpMehod) annotation).value();
                    } else if (annotation instanceof HttpParse) {
                        this.parse = ((HttpParse) annotation).value();
                    } else if (annotation instanceof HttpBaseUrl) {
                        this.url = ((HttpBaseUrl) annotation).value()+method.getName();
                    }
                }
                baseHttpClient = new Builder()
                        .url(this.url).method(this.method).setParse(this.parse)
                        .build();
                serviceMethodCache.put(method, baseHttpClient);
            } else {
                this.method = baseHttpClient.getMethod();
                this.parse = baseHttpClient.getParse();
                this.url = baseHttpClient.getUrl();
                baseHttpClient = this;
            }
            if (this.url.equals("")) {
                baseHttpClient.url = getConfiguration().getBaseUrl() + method.getName();
            }
            baseHttpClient.mParams = baseParams;
            getHttpImpl().execute(baseHttpClient, click);
        }
    }


         
发布了50 篇原创文章 · 获赞 7 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/Apple_hsp/article/details/54617789
今日推荐