Retrofit ではチュートリアルのアドレスhttp://square.github.io/retrofit/source
versionを使用します。
com.squareup.retrofit2:retrofit:2.5.0
ソースコードを見てみると、わかっているようで理解できないこともあります。非常にややこしいので、今回はソースコードを直接読んでデバッグしてみます。レトロフィットは実行プロセスを参照してください。
- 最初のステップでは、Retrofit オブジェクトを作成し、クリエイター モードを通じて Retrofit でいくつかのパラメータを設定し (特定のパラメータについてはソース コードを参照)、サンプルを実行します。
- 2 番目のステップは、Retrofit インスタンス オブジェクトを通じてメソッドを呼び出すことです
create(ApiService.class)
。このメソッドは、ApiService
プロキシ モードを通じてインターフェイス クラスのメソッド、アノテーション、およびパラメーターを解析します。そのプロセス内で、loadServiceMethod(method)
メソッド、アノテーション、パラメータをキャッシュすることによってprivate final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
。2回目のロード時はキャッシュから直接取り出してネットワークロード要求を行います。 - 3 番目のステップでは、リクエストが正常にロードされ、バックグラウンドから返されたデータに対して操作が実行されます。
ビルダー モードを通じて、Retrofit インスタンスを生成します。
/**
* 创建Retrofit 实例,并针对参数进行配置
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
//实例OkhttpClient对象
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
//默认配置返回参数适配器,例如,返回RxJava2CallAdapterFactory
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//会传一个默认的适配器
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
//默认配置返回的数据类型,比如GSON(GsonConverterFactory),XML,
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
//通过建造者模式,返回Retrofit实例
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
create() メソッドを呼び出してネットワークを要求します。
public <T> T create(final Class<T> service) {
//判断service 是否为接口类,若不是则抛异常
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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 Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
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);
}
});
}
上記からわかるように、プロキシ モードでは、そのApiService.class
中のメソッドmethod
、パラメータemptyArgs
、およびアノテーションloadServiceMethod(method)
がこのメソッドを通じて解析されます。
ServiceMethod<?> loadServiceMethod(Method method) {
//获取serviceMethodCache的缓存
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
//根据method获取网络请求实例
result = serviceMethodCache.get(method);
//如果缓存是空的
if (result == null) {
//则解析method
result = ServiceMethod.parseAnnotations(this, method);
//解析完成后,存入serviceMethodCache,
serviceMethodCache.put(method, result);
}
}
//返回网络请求实例
return result;
}
まずネットワーク リクエスト インスタンスをmethod
キャッシュから読み取りserviceMethodCache
、空でない場合はそのインスタンス オブジェクトを直接返します。
それ以外の場合は、ServiceMethod.parseAnnotations(this, method)
解析を通じて、完了後にresult
そのインスタンス オブジェクトをキャッシュに保存しますserviceMethodCache
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//主要的在这里,parseAnnotations
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 T invoke(Object[] args);
}
RequestFactory.parseAnnotations(retrofit, method);
上記から、このメソッドを通じてレトロフィットが実行され、メソッドが解析されてRequestFactory
オブジェクトが生成され、そのオブジェクトが解析HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
のためにメソッドに渡されてServiceMethod
ネットワーク要求オブジェクトが生成されることがわかります。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
//创建适配器,RxJava
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
//获取callAdapter响应类型
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//创建数据类型转换器,比如Gson,
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
//将其OkHttpClient对象 赋值给 callFactory
okhttp3.Call.Factory callFactory = retrofit.callFactory;
//将其解析完成的参数对象,传入HttpServiceMethod构造方法当中进行实例,并返回
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
retrofit,method,
2 つのインスタンス パラメーターを渡し、createCallAdapter(retrofit, method);
解析を渡し、callAdapter
インスタンス オブジェクトを返します。アダプターの変換と解析が完了すると、インスタンス オブジェクトcreateResponseConverter(retrofit, method, responseType);
が解析を通じて返されますresponseConverter
。最後にnew HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
インスタンス オブジェクトを返します。
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method) {
//获取方法返回的数据类型模型
Type returnType = method.getGenericReturnType();
//获取方法注解
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
//通过retrofit对象callAdapter方法进行解析,完事后返回适配器实例对象
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
method.getGenericReturnType()
データ型モデルとmethod.getAnnotations();
アノテーション配列が分析のためにメソッドに渡されretrofit.callAdapter(returnType, annotations)
、メソッドのアダプター型が返されることがわかります。
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
.....
//获取callAdapterFactories列表的索引,
int start = callAdapterFactories.indexOf(skipPast) + 1;
//针对列表进行循环查找,实例 CallAdapter适配器,返回该实例对象
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
省略以下代码
.....
throw new IllegalArgumentException(builder.toString());
}
callAdapterFactories
取得したリストの場所は、forループでオブジェクトを検索し、callAdapterFactories.get(i).get(returnType, annotations, this);
生成されたオブジェクトを返します。
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
省略部分代码
...
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
省略部分代码
...
throw new IllegalArgumentException(builder.toString());
}
converterFactories
取得したリストの場所は、forループでオブジェクトを検索し、converterFactories.get(i).get(returnType, annotations, this);
生成されたオブジェクトを返します。
private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
CallAdapter<ResponseT, ReturnT> callAdapter,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}
これが最後のステップで、new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
オブジェクトをインスタンス化します。実際、これはネットワーク リクエスト インスタンス オブジェクトですServiceMethod<T>
。
//调用传入网络方法请求参数
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
上記のパラメータはすべてOkHttpCall
ネットワークを通じてリクエストされ、バックグラウンドから返されたデータが分析されてコールバックされます。
1. ネットワークリクエストインターフェースクラス、
interface ApiService {
@GET("/article/list/{page}/json")
fun getListArticleData(@Path("page") page: Int): Call<BaseData<ArticleData>>
@GET("/project/list/{page}/json")
fun getListData(@Path("page") page: Int, @Query("cid") cid: Int): Call<BaseData<ArticleData>>
}
2. 一般的なインターフェイス アドレス クラス注: Hongyang Dashenによって提供されるインターフェイス アドレス
が使用され、自分でテストできます。
object ApiUrl {
val BASE_URL = "http://www.wanandroid.com"
var ARTICLE_LIST = "/article/list/{page}/json"
}
3. 使用方法
//配置
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
1.实例 Retrofit对象
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(ApiUrl.BASE_URL)
.build()
2.通过代理方法创建api接口类
val apiService = retrofit.create(ApiService::class.java)
3.调用接口内部的方法
val listArticleData = apiService.getListArticleData(1)
4.通过接口方法返回的实例进行回调,操作后台返回的数据
listArticleData.enqueue(object : Callback<BaseData<ArticleData>> {
//联网失败或数据解析失败
override fun onFailure(call: Call<BaseData<ArticleData>>, t: Throwable) {
println("t = $t")
}
//联网成功,后台返回数据
override fun onResponse(call: Call<BaseData<ArticleData>>, response: Response<BaseData<ArticleData>>) {
val mutableList: MutableList<ArticleData> = response.body()!!.data!!.datas as MutableList<ArticleData>
}
})
まず終わりにしましょう。
要約すると、私は 2 日間のソース コード調査を行いました。心で見つめれば、必ず得るものがあるのです。