Retrofit的简单封装

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chunqiuwei/article/details/84298053

Retrofit源码分析几篇博文中详细分析了Retrofit的内部原理,本篇再此基础上对Retrofit做了简单的封装。这次封装是基于所在项目中的情况进行的,可能不具有通用性。但是也算是一个基本思路。
如下图:
在这里插入图片描述
在看项目代码的时候发现如上图的接口方法很多,都有一个共性:就是方法参数一样,都是传一个map。不同的地方只是方法名字不同而已。

根据Retrofit源码分析系列博文我们知道每一个接口都会生成一个ServiceMethod对象并缓存起来。在项目中发现了数百个类似的接口,也就是说需要创建数百个ServiceMethod对象。现在有点不合适,所以我就对其进行了改造。

第一步:创建一个通用的post和get接口类,直接上代码:

interface BaseApi {
   //带参数的通用get请求
    @GET()
    Call<ResponseBody> executeGet( @Url String url, @QueryMap Map<String, Object> maps);
    
     //不带参数的通用get请求
    @GET()
    Call<ResponseBody> executeGet(@Url String url);
  
    //不带参数的通用post请求
    @POST()
    Call<ResponseBody> executePost( @Url String url);

  //带参数的通用post请求
    @POST()
    @FormUrlEncoded
    Call<ResponseBody> executePost( @Url String url, @FieldMap Map<String, Object> maps);

}

上面的get方法和post方法其返回值都是Call<ResponseBody>,那么我怎么怎么样自动返回所需的JavaBean呢,别急;且看第二步:

第二步:实现通用的get和post请求

先以同步get请求为例,为了转换特定类型的JavaBean,我们必须知道其Type类型,所以具体的get方法如下所示:

BaseApi baseApi = retrofit.create(BaseApi.class);

 //不带参数的同步get请求
  public <T> T doGetSync(Class<T> type, final String url) {
         //执行接口的get请求
          Call<ResponseBody> call = baseApi.executeGet(url);
             //执行网络请求
           Response<ResponseBody> response = call.execute();
          
          //获取baseApi的class对象
          Class<?> clas = baseApi.getClass();
           //获取executeGet的Method对象
            Method method = clas.getMethod("executeGet", new Class[]{String.class});
            //核心方法,查找对应的Converter对象
            Converter converter = retrofit.responseBodyConverter(type, method.getAnnotations());
          //进行对应的JavaBean转换
            if (converter != null) {
                return (T) converter.convert(response.body());
            }
      
        return null;
    }

上面方法关键有两处:
1、执行 baseApi.executeGet(url)方法获取一个Call<ResponseBody>对象,然后根据这个call对象执行execute同步请求方法,返回Response<ResponseBody>对象。
2、根据method的注解以及方法参数的type类型,调用retrofit.responseBodyConverter方法来获取对应的Converter对象,执行转换即可。
关键Converter的具体工作流程可查看Retrofit之Converter简单解析

使用起来也很简单:

YourBean bean = doGetSync(YourBean.class,"you api url")

异步请求有点特殊,因为需要回调结果给客户端,所以另外设置了一个接口:

    public interface IResponse<D> {
        void success(D data);

        void failure(Throwable t);

        /**
         * 返回JavaBean的class 对象 return YouBean.class
         * 以此来确定要转换的类型
         * @return
         */
        Type getDataType();
    }

那么一步请求就如下所示:

 public <T> void doGetAsync(final String url, final IResponse<T> res) {
     Call<ResponseBody> call = baseApi.executeGet(url);
        try {
           //异步请求
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    if (res == null) {
                        return;
                    }
                    try {
                        Class<?> clas = baseApi.getClass();
                        Method method = clas.getMethod("executeGet", new Class[]{String.class});
                        //根据resonse的getDataType来决定返回的类型
                        Converter converter = retrofit.responseBodyConverter(res.getDataType(), method.getAnnotations());
                        if (converter != null) {
                            T data = (T) converter.convert(response.body());
                            res.success(data);
                        }
                    } catch (Exception e) {
                   
                        res.failure(e);
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    if (res != null) res.failure(t);
                }
            });

        } catch (Exception e) {
  
            if (res != null) res.failure(e);
        }
    }

代码就是上面的代码,别的不多说了,直接贴如何使用的代码:

doGetAsync("http://api.apiopen.top/singlePoetry", new ZmHttp.IResponse<Bean>() {
            @Override
            public void success(Bean data) {
                 //请求成功
            }

            @Override
            public void failure(Throwable t) {
               //请求失败
            }

            @Override
            public Class getDataType() {
                return Bean.class;
            }
        });

到此为止,简单的封装挑选完毕。本次封装只是解决了如上文图中代码所示的api方法参数相同而方法名不同,导致方法越来越多的问题。如有不当之处欢迎批评指正。源码稍后风尚

猜你喜欢

转载自blog.csdn.net/chunqiuwei/article/details/84298053