CSDN:码小白

原文地址:

http://blog.csdn.net/sk719887916/article/details/51957819


前言

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

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

Retrofit :https://futurestud.io/blog

回顾Retrofit

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

简单列子

// 创建ApiService
public 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的原理进行理论分析,其实也没这个必要,推荐一篇其他人写的文章:

http://blog.csdn.net/woliuyunyicai/article/details/51479011

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

准备注解类

retrofit采用注解实现API,因此也模仿了准备多个注解接口,比如请求类型(GET),参数(Part),头部(header)等,

为了区分我用Tamic的开头用来做前缀先创建一个注解类TGet

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

Body 类似于Part

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



其他注解类没多大技术点,就不在列举

准备CallBack

此接口类用来回调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用法

实例化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的步伐…

最后感谢淘宝的测试地址:

URL:”http://ip.taobao.com/service/getIpInfo.php?ip=21.22.11.33“;

源码下载:

https://github.com/NeglectedByBoss/Tamic_Retrofit

导读:

- Retrofit 2.0

超能实践,完美支持Https传输


- Retrofit2.0

完美同步Cookie实现免登录

Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架的更多相关文章

  1. Android IntentService使用介绍以及源码解析

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.IntentService概述及使用举例 IntentService内部实现机制用到了HandlerThread,如果对HandlerThrea ...

  2. Android Handler机制(四)---Handler源码解析

    Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...

  3. 【Android应用开发】EasyDialog 源码解析

    示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...

  4. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...

  5. Android Handler机制(二)---MessageQueue源码解析

    MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...

  6. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  7. Android FM 模块学习之四 源码解析(1)

    Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE MicrosoftInternetExplorer4 前一章我们了解了FM手动调频,接下 ...

  8. Android HandlerThread使用介绍以及源码解析

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例              HandlerThread是什么鬼?其本质就是一个线程,但是Han ...

  9. Android FM模块学习之四源码解析(一)

    转自:http://blog.csdn.net/tfslovexizi/article/details/41516149?utm_source=tuicool&utm_medium=refer ...

随机推荐

  1. Discuz! 7.x 反射型xss

    引用:http://wooyun.jozxing.cc/static/bugs/wooyun-2014-084097.html 在/include/global.func.php 文件中 第1036- ...

  2. NPM实用指北

    npm作为下载node附送的大礼包,大家一定不会陌生. 然而关于npm,估计大量的只是用到npm install XXX以及npm run XXX. 其实这里边还有很多有意思的命令&参数.关于 ...

  3. [USACO17FEB]Why Did the Cow Cross the Road I S

    题目描述 Farmer John's cows are trying to learn to cross the road effectively. Remembering the old " ...

  4. 【USACO】股票市场

    题目描述 尽管奶牛天生谨慎,它们仍然在住房抵押信贷市场中大受打击,现在它们准备在股市上碰碰运 气.贝西有内部消息,她知道 S 只股票在今后 D 天内的价格. 假设在一开始,她筹集了 M 元钱,那么她该 ...

  5. 51nod 平均数(马拉松14)

    平均数 alpq654321 (命题人)   基准时间限制:4 秒 空间限制:131072 KB 分值: 80 LYK有一个长度为n的序列a. 他最近在研究平均数. 他甚至想知道所有区间的平均数,但是 ...

  6. poj 3384 半平面交

    Feng Shui Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5183   Accepted: 1548   Speci ...

  7. 习题7-1 uva 208(剪枝)

    题意:按最小字典序输出a到b 的所有路径. 思路:先处理出个点到目标点b的情况(是否能到达),搜索即可. 最开始我只判了a能否到b,然后给我的是WA,然后看了半天感觉思路没什么问题,然后把所有点都处理 ...

  8. Linux中LCD设备驱动-framebuffer(帧缓冲)【】

    转自:https://blog.csdn.net/linux_devices_driver/article/details/7079442 1.framebuffer 帧缓冲     帧缓冲(fram ...

  9. Spring学习笔记5——注解方式AOP

    第一步:注解配置业务类 使用@Component("Pservice")注解ProductService 类 package com.spring.service; import ...

  10. 前端工程师:电信专业转前端是如何拿到阿里、腾讯offer的?

    1.个人情况 ● 211本科 985硕士 电信专业 女生 ● 16年3月开始学习前端 ● 16年7月开始实习,共五家实习经历(不是特别厉害的厂) ● 秋招拿到两个offer(阿里.腾讯).没错只有这两 ...