前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >抛开理论,从实践中剖析Rertrofit原理

抛开理论,从实践中剖析Rertrofit原理

作者头像
开发者技术前线
发布2020-11-23 15:09:28
4830
发布2020-11-23 15:09:28
举报

Retrofit用法和介绍的文章实在是多的数不清,也有很多介绍其内部原理的,但是看过之后,还是让很多人云里雾里, 本篇文章旨在通过自我实现一个自定义的Retrofit,来熟悉了解其Retrofit的内部原理。也帮助针对那些项目很稳定,解决迁移API接口带来的难度问题。(本文实际上去年7月写的),再回过头来去了解retrofit源码想必是小菜一碟。

前言

Retrofit API用法和介绍的文章实在是多的数不清,也有很多介绍其内部原理的,但是看过之后,还是让很多人云里雾里, 花了堆的UML图,看完就忘了,本篇文章旨在通过自我实现一个模仿的Retrofit,来熟悉了解其Retrofit的内部原理。也帮助针对那些项目很稳定,解决迁移API接口带来的难度问题。

如果对Retrofit不熟悉的请先阅读Retrofit全介绍:

Retrofit :https://futurestud.io/blog

如果阅读外文吃力的话,建议阅读笔者之前的本系列文章。

回顾

Retrofit2.0是SQUARE美国一家移动支付公司最新发布的在Android平台上http的resultful访问客户端,具体简单用法列举!

简单列子

// 创建ApiServicepublic interface ApiService {    
    @GET("service/getIpInfo.php")    Call<IpResult> getData(@Query("ip") String ip);
    
}   
// 实例化Retrofit
   
   Retrofit retrofit = new Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl(url)
            .build();    
            
     // 构架ApiServiceImpl
    ApiService apiService = retrofit.create(ApiService.class);     
    
    // 执行异步请求
    Call<IpResult> call = apiService.getData("21.22.11.33");    
    
    call.enqueue(new Callback<IpResult>() {
        @Override        public void onResponse(Call<IpResult> call, Response<IpResult> response) {

        }

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

        }
    });

代码很简洁,很多人甚是羡慕,想想自己何时才能写出如此优雅的代码,也想弄明白其内部怎么实现的,今天就给大家带来一款Tamic框架,来模仿下Retrofit的实现原理。 下文开始之前,不会对Retrofit的原理进行理论分析,其实也没这个必要,推荐一篇其他人写的文章:

接着本次实现方式不会沿用Retrofit基于的okhttp, 因为okHttp本身实现了已进行了线程管理和回调,会给本次demo实现带来一定弊端,所以我选择用了SynchttpClient来做基础请求端,这样才能显得用零基础实现Retrofit, 本次实现需要涉猎到Java反射,依赖注入,控制反转,代理模式,建造者模式,面向接口编程等,这些技术这里不再重复介绍,retrofit最大的优势就是他的resutFul Api, ,下面接着看重点。

准备注解类

retrofit采用注解实现API,因此也模仿了准备多个注解接口,诸如请求类型(GET),参数(Part),头部(header)等, 为了区分我用Tamic的开头T字母用来做前缀,先创建了一个注解类TGet

// 请求方式
@Target(ElementType.METHOD)
public @interface TGet { String value();
}

再搞个@TBody ,类似retofit的@Part注解

// 参数@Retention(RetentionPolicy.RUNTIME)
  public @interface TBody {  String value();
}

其他注解类没多大技术点,贮备好上图的注解类,一个POST 一个Head, 其方式一样,源码就不在列举。

回调接口

此接口类用来回调http请求结果,采用泛型,方便上层注入数据model,动态解析返回实体

public interface ICallback<T> { void success(T t); void failed(Throwable e);
 }

Platform

Platform用来调度多个请求线程,

public class Platform { 
 private static final Platform PLATFORM = findPlatform();
 
 public static Platform get() {
    Log.v(TamicHttpClient.TAG, PLATFORM.getClass().toString());    
    return PLATFORM;
}
  private static Platform findPlatform() {   
   try {
        Class.forName("android.os.Build");        
        if (Build.VERSION.SDK_INT != 0) {            
        return new Android();
        }
    } catch (ClassNotFoundException ignored) {
    }    
    return new Platform();
}
public Executor defaultCallbackExecutor() {    
   return new HandleThreadPool().getExecutor();
}
public Object execute(Runnable runnable) {
    defaultCallbackExecutor().execute(runnable);    
    return null;
}
static class Android extends Platform {    
@Override
    public Executor defaultCallbackExecutor() {        
    
        return new HandleThreadPool().getExecutor();
    }
  }

Tamic

构建类似Retrofit一样的bulid模式的API工厂,此类主要用反射解析和代理ApiService,用来执行具体网络访问请求,动态解析泛型数据模型,回调服务端返回的请求结果,返回上层便于UI更新。

Tamic(Context context, String baseUrl, AsyncHttpClient client) {     
  this.context = context;     
  this.baseUrl = baseUrl;     
  this.client = client;
}

/**
 * public interface CategoryService {
 * @POST("category/{cat}/")
 * Call<List<Item>> categoryList(@Path("cat") String a, @Query("page") int b);
 * }
 */
 
 public <T> T create(final Class<T> clazz) {    
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(),            
        new Class[]{clazz},  new InvocationHandler() {               
         @Override
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                    performeParser(proxy, method, args);                    return execute();
                }
            });
}

此是Tamic内部类builder大致图,具体代码可以去github阅读,主要用来构建上层添加baseUrl,超时等接口,实例化AsyncHttpClient等

线程池工厂

用来管理和复用线程,避免线程溢出造成内存泄露,不是本次关注的点,略去


实现好了自己的Retrofit,接下来再看看怎样使用,观察下和Retrofit用法有什么区别?

Tamic用法

依赖

repositories {    
        jcenter()    
                 
        maven { url "https://jitpack.io" }
dependencies {
   
   compile 'com.tamic:tamicLibrary:1.0.2'
  

}

实例化Tamic (Retrofit)

Tamic tamic = new Tamic.Builder(MainActivity.this)
            .baseUrl("http://ip.taobao.com/")
            .connectTimeout(5)
            .addLog(true)
            .build();

APIService

public interface ApiService {

@TGet("service/getIpInfo.php")
Call<IpResult> getData(@TBody("ip") String ip,ICallback<IpResult> callBack);

    }

Create Service

ApiService service = tamic.create(ApiService.class);

Execute

service.getData("21.22.11.33", new ICallback<IpResult>() {        
      @Override
        public void success(IpResult ipResult) {              
         // todo
        }       
         @Override
        public void failed(Throwable e) {            
         // todo
        }
    });

不华丽的结束

给下面按钮给个点击事件,用来执行请求,在回调中显示一条Toast, 看看测试结果:

测试结果

数据成功请求到,并且被框架自动解析返回JavaBean

既然功能和Retrofit很相似,和Retrofit几乎一摸一样,不妨我们再看看的工程配置 :

compile 'com.loopj.android:android-async-http:1.4.9' compile 'com.alibaba:fastjson:1.2.12'

果不其然,并没有关于Retrofit的任何依赖,说明我们的Tamic并无投机取巧。 本次实现只关注Retrofit整体了一个流程思想,其他Retrofit的功能其实就通过以上思想来扩展的,设置解析工厂,返回内容格式,文件上传,下载等,本次实现并没有深入模仿,因为Retrofit整个流程思想比较系统,其他Api和普通Get请求一样,稍微改造一下就可以了。 与其说是对Retrofit的借鉴,还不如是对Ioc和Aop思想的综合运用。大家也发现本次主要学习依赖注入,和控反转的AOP思想,以及加入代理和接口编程,旨在以后的开发道路上能自我实现一种开发框架,如果感兴趣的同学可以去自我模仿一个RxJava. 如果你目前项目非常大,网络接口一直以前的httpclient的朋友,可以大但的迁移到Retrofit,只要你稍微做下接口适配,就能很好的让老旧Api接通Retrofit,或者也可以将老Api改造成属于你的Retrofit请求端!领导都无法阻止你用Retrofit的步伐…

源码:https://github.com/Tamicer/Tamic_Retrofit

技术 - 资讯 - 感悟

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发者技术前线 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 回顾
  • 准备注解类
  • 回调接口
  • Platform
  • Tamic
  • 线程池工厂
  • Tamic用法
    • 依赖
      • 实例化Tamic (Retrofit)
        • APIService
          • Create Service
            • Execute
              • 不华丽的结束
              相关产品与服务
              云支付
              云支付(Cloud Pay,CPay)为您提供开放、可靠的聚合收款技术服务和商户管理功能。云支付支持刷卡支付、扫码支付、一码多付多种支付方式。服务商也可使用云支付提供的 SDK 和 HTTPS 接口,将云支付集成进自己的系统中,为商户提供的个性化解决方案。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档