Retrofit2源码解析(一)

  1. 云栖社区>
  2. 博客>
  3. 正文

Retrofit2源码解析(一)

xxq2dream 2018-09-13 23:22:36 浏览1409
展开阅读全文

本文基于Retrofit2的2.4.0版本

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

Retrofit2底层基于OkHttp3,是对利用OkHttp3请求网络的一种封装,可以使我们避免写很多重复的调用网络请求的代码,同时灵活性很高,可以定制自定义的OkHttpClient、自定义的数据解析转换器(比如Gson、Jackson等)、自定义的请求转换器(比如结合RxJava)。

Retrofit2的另一个特点就是使用运行时注解,我们在使用时可以根据需要来利用注解将我们的业务调用接口转换成Http请求的接口。

下面先来看看我们使用Retrofit2发起网络请求的步骤

(1)创建我们的具体业务接口,这里比如我们调用淘宝的IP地址库

public interface MyService {
    @GET("getIpInfo.php=11.11.11.11")
    Call<IpBean> getData();
}

(2)创建Retrofit

retrofit = new Retrofit.Builder()
    .baseUrl("https://ip.taobao.com/service/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

可见Retrofit2采用的是Builder模式来构建的

(3)利用Retrofit创建我们的接口对象,生成Call对象,并调用请求网络方法

MyService myService = retrofit.create(MyService.class);
Call<IpBean> call = myService.getData();
call.enqueue(new Callback<IpBean>() {
    @Override
    public void onResponse(Call<IpBean> call, Response<IpBean> response) {
        
    }

    @Override
    public void onFailure(Call<IpBean> call, Throwable t) {
        
    }
});

Retrofit的创建

首先我们看看创建Retrofit时都做了哪些工作

public Retrofit build() {
    //这里可以看出我们必需设置baseUrl
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }
    
    //如果我们没有设置自定义的OkHttpClient,就用默认的OkHttpClient
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
        callFactory = new OkHttpClient();
    }
    
    //这个callbackExecutor用于回调到UI线程
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    //将我们设置的Call适配器添加到列表中,比如RxJava的适配器
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    //添加默认的Call适配器
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    // Make a defensive copy of the converters.
    List<Converter.Factory> converterFactories =
            new ArrayList<>(1 + this.converterFactories.size());

    //添加数据转换器,用于将网络请求返回的结果转换成我们需要的类型
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    
    //构建Retrofit
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

通过上面Retrofit2的Builder的build方法,我们可以看出在Retrofit2中主要有这么几个部分:

(1)用于执行具体网络请求的callFactory,也就是OkHttpClient。所以说Retrofit2是基于OkHttp3的封装。

(2)callbackExecutor回调执行器,这个是用于网络请求返回后回调到主线程的。我们知道,在利用OkHttp3进行网络请求时,我们需要手动回调到主线程,以便更新UI。那我们来看看这个默认的defaultCallbackExecutor是不是这样。

//Retrofit.class
public Builder() {
    this(Platform.get());
}

Builder(Platform platform) {
    this.platform = platform;
}

可以看到在Builder中调用的是Platform的get方法,返回对应的平台,然后在build方法里通过platform的defaultCallbackExecutor得到我们的回调器。下面我们看看这个Platform类

class Platform {
    private static final Platform PLATFORM = findPlatform();

    static Platform get() {
        return PLATFORM;
    }

    private static Platform findPlatform() {
        try {
            Class.forName("android.os.Build");
            if (Build.VERSION.SDK_INT != 0) {
                return new Android();
            }
        } catch (ClassNotFoundException ignored) {
        }
        try {
            Class.forName("java.util.Optional");
            return new Java8();
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform();
    }
    
    ...
    
    static class Android extends Platform {
        @Override
        public Executor defaultCallbackExecutor() {
            return new MainThreadExecutor();
        }

        @Override
        CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
            if (callbackExecutor == null) throw new AssertionError();
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }

        static class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());

            @Override
            public void execute(Runnable r) {
                handler.post(r);
            }
        }
    }
}

从上面的源码中我们可以看到Platform中会根据当前运行的平台返回不同的子类,这里当然就是Android这个内部类了。所以当我们调用platform的defaultCallbackExecutor时,实际上调用的是Android这个类的defaultCallbackExecutor方法,而这个方法返回的是MainThreadExecutor,它的作用就是利用handler将执行结果回调到主线程中。

(3)callAdapterFactories适配器列表,这里面存放的是所有的Call适配器CallAdapter。这个CallAdapter是干嘛的呢?我们知道Retrofit2底层是用Okhttp3来请求网络的,那势必是通过OkHttp3的Call来执行请求,但是我们在实际使用Retrofit2时,可能需要结合请他的三方库,常见的比如RxJava,那我们接口中所需要返回的可能就是Observable而不是Call了。

@GET("getIpInfo.php?ip=11.11.11.11")
Observable<IpBean> getObservableData();

所以Retrofit2就需要一个Call适配器CallAdapter,来将Call转换为我们需要的Observable,这就是CallAdapter的作用。

(4)converterFactories返回结果转换器列表,这里面存放的是将网络返回结果,也就是OkHttp3返回的Response,解析转换成我们需要的实际类型,比如IpBean实体类。如GsonConverterFactory就是一个常用的转换器,相当于Retrofit2把我们直接使用Okhttp3来请求网络数据时需要将返回结果进行Gson解析的动作也替我们做了。

总结

(1)这里我们简单分析了Retrofit的创建过程,可以发现Retrofit中核心部分包括OkHttpClient、Call适配器、Response转换器以及用于将请求回调到UI线程的回调执行器等。

(2)Retrofit的创建采用的是Builder模式,定制化程度很高,我们可以设置自己的OkHttpClient,也可以实现自定义的Call适配器和Response转换器,以及请求的回调执行器。

(3)可见Retrofit虽然做了很大程度的封装,但是灵活性扩展性依然很高,我们几乎可以扩展更改网络请求的大部分过程。

今天我们先浅尝则止,后面我们再来具体分析下Retrofit2的网络调用过程,看看Retrofit2是怎么利用适配器模式来为我们提供强大的灵活性的,敬请期待。



欢迎关注我的微信公众号,和我一起每天进步一点点!
AntDream

网友评论

登录后评论
0/500
评论
xxq2dream
+ 关注