共计 12595 个字符,预计需要花费 32 分钟才能阅读完成。
1. Retrofit简介
Retrofit是Square公司的又一力作,针对Android网络请求的框架,遵循Restful设计风格,底层基于OkHttp。
他对比其他框架
性能最好
封装程度高,拓展性差
简介易用,代码简单
解耦彻底
可以非常方便的与RxJava连用
2. Retrofit用法(异步)
2.1 添加依赖
可以在Retrofit Github库页面里面找到最新版本号,我写这篇博客时最新版导入方式
在你项目的app的build.gradle里面添加implementation 'com.squareup.retrofit2:retrofit:2.6.1'
同时,如果你需要配套的数据转换器还需要导入以下的依赖
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
2.2 添加网络权限
在你APP的AndroidManifest.xml里添加<uses-permission android:name="android.permission.INTERNET"/>
2.3 创建 接收服务器返回数据 的类
Reception.java
1 2 3 4
puublic class Reception { ... }
2.4 创建 用于描述网络请求 的接口
GetRequest_Interface.interface
1 2 3 4 5 6 7 8 9
public interface GetRequest_Interface { @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car") Call<Translation> getCall () ; }
2.5 创建Retrofit实例
1 2 3 4 5
Retrofit retrofit = new Retrofit .Builder() .baseUrl("http://fanyi.youdao.com/" ) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
2.6 创建网络请求接口实例
1 2 3 4 5
GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);Call<Reception> call = request.getCall();
2.7 发送网络请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
call.enqueue(new Callback <Translation>() { @Override public void onResponse (Call<Translation> call, Response<Translation> response) { response.body().show(); } @Override public void onFailure (Call<Translation> call, Throwable throwable) { System.out.println("连接失败" ); } });
2.8 处理返回数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
call.enqueue(new Callback <Translation>() { @Override public void onResponse (Call<Translation> call, Response<Translation> response) { response.body().show(); } @Override public void onFailure (Call<Translation> call, Throwable throwable) { System.out.println("连接失败" ); } });
由于本文的核心不是讲用法,所以关于用法这块,我并没有多讲,大家若想多了解,可以看此博客:这是一份很详细的 Retrofit 2.0 使用教程(含实例讲解)
3. Retrofit源码
3.1 Retrofit对象构造源码
应对一个框架的源码首先从使用它的地方开始,我们先来看Retrofit的创建代码:
1 2 3 4
Retrofit retrofit = new Retrofit .Builder() .baseUrl("http://fanyi.youdao.com/" ) .addConverterFactory(GsonConverterFactory.create()) .build();
我们可以把它分为5个部分来分析源码:
我们首先来看第一步
3.1.1 步骤1:Retrofit类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
public final class Retrofit { private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap <>(); final okhttp3.Call.Factory callFactory; final HttpUrl baseUrl; final List<Converter.Factory> converterFactories; final List<CallAdapter.Factory> callAdapterFactories; final @Nullable Executor callbackExecutor; final boolean validateEagerly; Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories, @Nullable Executor callbackExecutor, boolean validateEagerly) { this .callFactory = callFactory; this .baseUrl = baseUrl; this .converterFactories = converterFactories; this .callAdapterFactories = callAdapterFactories; this .callbackExecutor = callbackExecutor; this .validateEagerly = validateEagerly; } ... }
可以看到,Retrofit的构造方法需要一次性把需要的数据全部准备好。 而且这块有特别多的工厂,使用了工厂模式。这个我们之后再讲,接下来看步骤2:
3.1.2 步骤2:Builder()方法
我们先来看下Builder()方法的源码:
1 2 3
public Builder () { this (Platform.get()); }
这里调用了Rlatform.get()方法:
1 2 3
static Platform get () { return PLATFORM; }
PLATFORM的定义就在上面:
1
private static final Platform PLATFORM = findPlatform();
我们再来看下findPlatform()方法:
1 2 3 4 5 6 7 8 9 10
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 (true ); }
这块创建了一个Android对象,接着返回了传入true创建的Platform对象。我们再来看下Android类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
static final class Android extends Platform { Android() { super (Build.VERSION.SDK_INT >= 24 ); } @Override public Executor defaultCallbackExecutor () { return new MainThreadExecutor (); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler (Looper.getMainLooper()); @Override public void execute (Runnable r) { handler.post(r); } } }
3.1.3 步骤3:baseUrl()方法
1 2 3 4
public Builder baseUrl (String baseUrl) { Objects.requireNonNull(baseUrl, "baseUrl == null" ); return baseUrl(HttpUrl.get(baseUrl)); }
最后还是调用了一个baseUrl()方法,我们来看看这个baseUrl()方法:
1 2 3 4 5 6 7 8 9 10 11
public Builder baseUrl (HttpUrl baseUrl) { Objects.requireNonNull(baseUrl, "baseUrl == null" ); List<String> pathSegments = baseUrl.pathSegments(); if (!"" .equals(pathSegments.get(pathSegments.size() - 1 ))) { throw new IllegalArgumentException ("baseUrl must end in /: " + baseUrl); } this .baseUrl = baseUrl; return this ; }
步骤3用于设置网络请求的Url
3.1.4 步骤4:addConverterFactory()方法
我们先来看看GsonConverterFactory.create()方法:
1 2 3
public static GsonConverterFactory create () { return create(new Gson ()); }
又调用了另一个create()方法:
1 2 3 4
public static GsonConverterFactory create (Gson gson) { if (gson == null ) throw new NullPointerException ("gson == null" ); return new GsonConverterFactory (gson); }
如果传入的gson为空就报异常,不为空就调用GsonConverterFactory的构造方法:
1 2 3
private GsonConverterFactory (Gson gson) { this .gson = gson; }
所以这个方法本质就是返回了一个gson对象给了addConverterFactory()方法,那我们再来看看这个方法:
1 2 3 4 5
public Builder addConverterFactory (Converter.Factory factory) { converterFactories.add(Objects.requireNonNull(factory, "factory == null" )); return this ; }
步骤4创建了一个含有Gson实例的GsonConverterFactory对象,并放入了ConverterFactory。
3.1.5 步骤5:build()方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
public Retrofit build () { if (baseUrl == null ) { throw new IllegalStateException ("Base URL required." ); } okhttp3.Call.Factory callFactory = this .callFactory; if (callFactory == null ) { callFactory = new OkHttpClient (); } Executor callbackExecutor = this .callbackExecutor; if (callbackExecutor == null ) { callbackExecutor = platform.defaultCallbackExecutor(); } List<CallAdapter.Factory> callAdapterFactories = new ArrayList <>(this .callAdapterFactories); callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList <>( 1 + this .converterFactories.size() + platform.defaultConverterFactoriesSize()); converterFactories.add(new BuiltInConverters ()); converterFactories.addAll(this .converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit (callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
按前面配置的变量,将Retrofit所有的变量都配置好,最后完成创建Retrofit实例。
到这Retrofit的创建部分就完了。 Retrofit通过建造者模式创建了一个Retrofit实例:
请求工厂callFactory:默认是OkHttpClient
数据转换器工厂converterFactories
网络请求适配器工厂callAdapterFactories:默认是ExecutorCallAdapterFactory
回调执行器callbackExecutor
3.2 创建网络请求接口的实例
大致创建方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<!-- Reception.java --> puublic class Reception { ... } <!-- GetRequest_Interface.interface --> public interface GetRequest_Interface { @GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car") Call<Translation> getCall () ; } <!-- MainActivity.java --> GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);Call<Reception> call = request.getCall();
我们先看看retrofit.create()干了啥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public <T> T create (final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class <?>[] { service }, new InvocationHandler () { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object [0 ]; @Override public @Nullable Object invoke (Object proxy, Method method, @Nullable Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this , args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
首先调用了validateServiceInterface()这个方法,我们来看看这个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
private void validateServiceInterface (Class<?> service) { if (!service.isInterface()) { throw new IllegalArgumentException ("API declarations must be interfaces." ); } Deque<Class<?>> check = new ArrayDeque <>(1 ); check.add(service); while (!check.isEmpty()) { Class<?> candidate = check.removeFirst(); if (candidate.getTypeParameters().length != 0 ) { StringBuilder message = new StringBuilder ("Type parameters are unsupported on " ) .append(candidate.getName()); if (candidate != service) { message.append(" which is an interface of " ) .append(service.getName()); } throw new IllegalArgumentException (message.toString()); } Collections.addAll(check, candidate.getInterfaces()); } if (validateEagerly) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) { loadServiceMethod(method); } } } }
获取到Platform(平台),然后再遍历接口中的方法,调用loadServiceMethod()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13
ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null ) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null ) { result = ServiceMethod.parseAnnotations(this , method); serviceMethodCache.put(method, result); } } return result; }
这个方法主要就是通过serviceMethodCache来存储转换为ServiceMethod类型的Method。
那我们在回过去看InvocationHandler的invoke()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
new InvocationHandler () { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object [0 ]; @Override public @Nullable Object invoke (Object proxy, Method method, @Nullable Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this , args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } });
两个if先不管,先看最后的return,可以看到他调用了一个loadServiceMethod()方法,而这个方法在前面就说过,主要就返回了一个ServiceMethod。那我们接着来看invoke()方法: 按住command+鼠标左键进入后,显示的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
abstract class ServiceMethod <T> { static <T> ServiceMethod<T> parseAnnotations (Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s" , returnType); } if (returnType == void .class) { throw methodError(method, "Service methods cannot return void." ); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke (Object[] args) ; }
这个invoke()根本就是个抽象方法啊,然后我又回去找看看有没有说是哪个继承自ServiceMethod的类实现了这个方法,结果也没找到,最后想到了AndroidStudio可以command+左键找实现了这个类的地方啊。于是我就点了下这个类,结果成功找到了HttpServiceMethod这个类,他是ServiceMethod的子类中唯一一个实现了invoke()方法的:
1 2 3 4
@Override final @Nullable ReturnT invoke (Object[] args) { Call<ResponseT> call = new OkHttpCall <>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
可以看到这块他创建了一个OkHttpCall对象,此处不做详解,可以看我关于OkHttp的一篇博客:Android网络请求3—解析OkHttp源码 。然后调用了adapt方法,我们来看看这个方法:
1
protected abstract @Nullable ReturnT adapt (Call<ResponseT> call, Object[] args) ;
这又是一个抽象方法。只不过好的是,这个方法下面我们就找到了他的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
static final class CallAdapted <ResponseT, ReturnT> extends HttpServiceMethod <ResponseT, ReturnT> { private final CallAdapter<ResponseT, ReturnT> callAdapter; CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, ReturnT> callAdapter) { super (requestFactory, callFactory, responseConverter); this .callAdapter = callAdapter; } @Override protected ReturnT adapt (Call<ResponseT> call, Object[] args) { return callAdapter.adapt(call); } }
可是他又返回给了一个CallAdapter接口的实现类的adapt()方法。。。。艹
所以,这块我就不懂了,我不知道他到底咋实现这个的这个方法的,我看了《Android进阶之光》和其它很多博客,他们都是老版本的Retrofit,create()方法不同,而且调用的adapt()方法也不同。。。
3.3 网络请求
网络请求这块Retrofit实际上就是用OkHttp实现的,所以这块我就不在这多说了,大家要了解的可以看我之前写的博客:Android网络请求3—解析OkHttp源码 。