重识Retrofit

作者: OpenDreamer | 来源:发表于2016-10-20 19:09 被阅读1598次

    这是我第三次接触他,之前放弃原因之一是感觉他不好用,尤其是在实际项目中。实际项目中往往会有一个页面有多个请求,这样的话就需要实现多个回调接口,回调接口多了代码就会显的杂乱;原因之二并没有发现太多优势。现在又来重新了解他主要因为我想写一个通用的框架,其次是我想多接触一些新的框架以及代码风格。 开头先給大家说一下本本的结构。本文首先会介绍最简单的使用方法。使用对大多数人应该是最有吸引力的,它能最直接的检验框架是否值得去引入以及研究,因此这里把它放在最前面。接着是简单源码分析的原理,然后是详细的源码分析,再然后是框架中值得借鉴的代码风格。最后是我写的一个基础的网络请求框架。
    一、最简单的使用
    1.定义一个接口

    public interface ApiService<T> { @POST("top250")
    Observable<MovieBean>getMovie( @Query("start") int start, @Query("count") int count);}
    
    

    2.初始化Retrofit

    Retrofit retrofit=new Retrofit.Builder() 
    .baseUrl(ApiConfig.BASE_URL_JOKE)
     .client(okHttpClient)
     .addConverterFactory(GsonConverterFactory.create()) 
    .build();
     Call<ResponseBody> call=retrofit.create(ApiService.class);
    
    

    3.网络请求

    call.enqueue(new Callback<ResponseBody>() { 
    @Override public void onResponse( Call<ResponseBody> call,final Response<ResponseBody> response) { }
     @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } });
    
    

    从上面的代码不难看出他有一下优点:1.不用像异步任务那样为每个请求定义一个异步请求类,以及相关回调接口。2.不用像使用IntentService那样考虑反回值的处理。

    二、简单的原理 由于粘贴源码不便于阅读以及分析,所以这里尝试了新的方式,使用流程图把整个流程大概的介绍了一遍。大家看的时候可以对照着源码看流程图,这样更便于理解。


    retrofit简单流程图.png

    三、详细的原理




    这里由于图片过大,所以分成了三部分加载

    四、代码中有意思和值得借鉴的地方 1.代码中可能比较难理解的可能就是代理模式了,代理模式平常的项目中就我而言是基本上不用的,这次也补了很多的课,代理有静态代理和动态代理,静态代理简单的来说就是一个接口和一个实现该接口类的关系例如下面的代码:

     interface People{
     void motherTongue();}
    class ChinesePeople implements People{ 
    void motherTongue(){ Lod.g("test","speak chinese");} }
    // 在主线程中调用 
    People people=new ChinesePeople(); 
    people.motherTongue();输出的会是 speak chinese;
    
    

    `在Retrofit框架中使用的是动态代理。动态代理是在运行时,通过反射机制实现动态代理,并且能够代理各种类型的对象。安卓提供了一个产生动态代理的类Proxy.newProxyInstance,使用它可以轻松实现代理。

     interface AgentTest{ void agentTest(); }
    在主流程中加入下面代码
    AgentTest agentTest=(AgentTest) Proxy.newProxyInstance(AgentTest.class.getClassLoader(), new Class[]{AgentTest.class},
     new InvocationHandler() {
     @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     Log.d("test","---I am here"); return null; } }); 
    agentTest.agentTest(); //控制台会输出 --- I am here 这里和源码中的invoke 方法被调用是一样的
    
    

    代理在平常项目中用的比较少,但一些比较出名的框架中都会包含,不得不说他是一种不错的设计模式。不过具体的好处还得是多用才能感受出来。
    2、个性的使用 Retrofit中有默认的OkHttpClient,有默认的CallAdapterFactory,但他同时有支持我们去使用自己的。这一点在框架的设计是十分必要的,因为框架毕竟不可能永远通用,那就会有一个升级的过程,像他这样的话,升级相当于只用升级部分的对象替换以前的对象就可以了,不用去改主框架。下面这段源码感觉也有值得借鉴的,和大家分享一下。

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
    CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this); 
    if (adapter != null) { return adapter; }}
    

    这段源码是Retrofit类中nextCallAdapter()方法中的部分代码。它用list作为容器。存储CallAdapterFactory,并且使用第0个。再填加自己的CallAdapterFactory 时是再bulider的过程添加的,而添加默认的 CallAdapterFactory是再create()中添加的,因此如果有自定义的CallAdapterFactory肯定会在最前面,从而被选用。

    五、基础的网络请求框架demo地址 框架结合了RxJave和Retrofit,并进行了简单的封装,对返回的内容没有使用GsonConverterFactory转换对象。主要原因是考虑到不同的对象需要不同的返回接口,其次一些返回内容单独定义一个类的话,会产生很多实体类。在实际的应用项目中会出现一个一面调用多个接口,有的时候也需要用到请求时的参数,所以封装的时候将参数也封装在返回的结果里,这样有利于使用和区分不同的请求

    相关文章

      网友评论

        本文标题:重识Retrofit

        本文链接:https://www.haomeiwen.com/subject/irnfuttx.html