Android网络请求Retrofit核心技术实现

本文深入探讨了Android中Retrofit网络请求的核心实现,包括Retrofit的使用方式、Builder模式分析、ServiceMethod、ParameterHandler和RequestBuilder。通过源码解析,详细介绍了Retrofit如何通过动态代理服务实现请求,涉及注解解析、请求构建和发起网络请求的关键步骤。总结了Retrofit的核心组件及其作用,帮助理解Retrofit的工作原理。
摘要由CSDN通过智能技术生成
前言
	最近在学习和整理安卓框架架构知识,看到了Retrofit这一块,想想这块的内容还是前两年接触的,但是一直只是停留在能够使用Retrofit完成任务开发的应用层,对他的核心业务逻辑没有功夫细看,现在整好手里的工作也不忙,在梳理自己的知识体系,就想把这部分内容深入了解一下,从源码角度看看他到底都做了哪些事,关于适配器,和回调工厂,gson处理和数据转换这部分,我还没分析,所以先把整体的实现网络请求的核心逻辑部分梳理一下, 希望大家能看的懂,一起学习,共同进步。接下里会整理关于适配器工厂,和数据转换部分的内容。
1. Retrofit如何应用

1.1 添加依赖

implementation 'com.squareup.retrofit2:retrofit:2.1.0'

1.2 使用方式

接口使用方式`在这里插入代码片`
private final static String IP = "144.34.161.97";
    private final static String KEY = "aa205eeb45aa76c6afe3c52151b52160";
    private final static String BASE_URL = "http://apis.juhe.cn/";

    interface HOST {
   

        @GET("ip/ipNew")
        Call get(@Query("ip") String ip, @Query("key") String key);

        @POST("ip/ipNew")
        Call post(@Field("ip") String ip, @Field("key") String key);
        
        }

1.3 开发测试使用

@Test
    public void testRetrofit() throws Exception {
   
    //1.通过builder 模式创建Retrofit的实例并生成build
        Retrofit retrofit = new Retrofit.Builder()
                .getBaseUrl(BASE_URL)
                .build();
         //2. 根据接口的class类通过create创建相应的操作类Class       
        HOST host = retrofit.create(HOST.class);

        //3.RETROFIT GET同步请求
        {
   
            Call call = host.get(IP, KEY);
            Response response = call.execute();
            if (response != null && response.body() != null) {
   
                System.out.println("Retrofit GET同步请求 >>>" + response.body().string());
            }
        }
        //3.Retrofit Post同步请求
        Call call = host.post(IP, KEY);
        Response response = call.execute();
        if (response != null && response.body() != null) {
   
            System.out.println("Retrofit POSt同步请求 >>>" + response.body().string());
        }

    }

上面的代码便是Retrofit网络请求的全部代码了,接下来我们看看打印结果:

Retrofit GET同步请求 >>>{
   "resultcode":"200","reason":"查询成功","result":{
   "Country":"美国","Province":"加利福尼亚","City":"","Isp":""},"error_code":0}
Retrofit POSt同步请求 >>>{
   "resultcode":"200","reason":"查询成功","result":{
   "Country":"美国","Province":"加利福尼亚","City":"","Isp":""},"error_code":0}
2. Retrofit的分析

我们先从源码入手分析:
我们可以看到Retrofit的整体体思想是以Builder建造者模式设计的,那么我们就从Builder开始分析 为了简化代码,便于挑出retrofit的整体思想框架所以我们先根据他的源码,进行简化处理一下,处理后的代码如下

public class Retrofit {
   
    private HttpUrl mBaseUrl;
    private Call.Factory mFactory;
    private final Map<Method, ServiceMethod> mServiceMethodCache = new ConcurrentHashMap<>();

    Retrofit(Builder builder) {
   
        this.mBaseUrl = builder.mBaseUrl;
        this.mFactory = builder.mFactory;
    }

    //提供对外的API调用

    public Call.Factory callFactory() {
   
        return mFactory;
    }


    public HttpUrl baseUrl() {
   
        return mBaseUrl;
    }


    /***
     * 使用动态代理的方式创建定义的接口类
     * @param service
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T create(Class<T> service) {
   

        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{
   service}, new InvocationHandler() {
   
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
                ServiceMethod serverMethod = loadServiceMethod(method);
                return new OkHttpCall(serverMethod, args);
            }
        });
    }

    /***
     * 加载代理服务的方法
     * @param method (get两次避免第二次从缓存中拿到的为空 ,因为第一次new 的时候执行了同步)
     * @return
     */
    ServiceMethod loadServiceMethod(Method method) {
   


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

        }

        return result;
    }


    public static final class Builder {
   

        private HttpUrl mBaseUrl;
        private Call.Factory mFactory;

        public Builder getBaseUrl(String baseUrl) {
   
            if (baseUrl.isEmpty()) {
   
                throw new NullPointerException("baseUrl == null");
            }
            this.mBaseUrl = HttpUrl.parse(baseUrl);
            return this;
        }

        public Builder callFactory(Call.Factory factory) {
   
            this.mFactory = factory;
            return this;
        }

        public Retrofit build() {
   
            if (mFactory == null) {
   
                mFactory = new OkHttpClient();
            }
            return new Retrofit(this);
        }

    }
}

我们看到Retrofit主要定义了三个属性(因为这里我们先不考虑线程调度和适配器模式)

    private HttpUrl mBaseUrl;
    private Call.Factory mFactory;
    private final Map<Method, ServiceMethod> mServiceMethodCache = new ConcurrentHashMap<>();

第一个是HttpUrl 主要是处理我们的请求路径,也就是最前面的路径类似于:http://www.xxx.com 第二个是一个Factory,实际上它是okhttp的 call的接口。里面定义了call newCall(Request request),因为Retrofit的底层实际上是用的是okhttp,他相当于对okhttp做了进一步的封装,更具有拓展性。 第三个是一个ServiceMethod的Map集合,涉及到自定义注解,这个我们之后会讲到 这是一个重点。

对于Builder 我们就不多做解释了他就是一个建造者模式的常用类,我们需要在这里对方法属性进行赋值并且返回Builder,并通过Build方法new 一个Retrofit(this),传入builder ,因为在retrofit中我们需要使用这个builder如下:

Retrofit(Builder builder) {
   
        this.mBaseUrl = builder.mBaseUrl;
        this.mFactory = builder.mFactory;
    }

这里不给他设置访问修饰符,是为了不可以被其他类实例化,有的人觉得那可以使用单例,这个不能使用单例,可能会造成内存泄漏.

2.2 我们可以看到在一个Retrofit中有这样一个方法

/***
     * 使用动态代理的方式创建定义的接口类
     * @param service
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T create(Class<T> service) {
   

        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{
   service}, new InvocationHandler() {
   
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
                ServiceMethod serverMethod = loadServiceMethod(method);
                return new OkHttpCall(serverMethod, args
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值