1, use,

1. Create HTTP interfaces

First, the API service interface of HTTP is created. A method under the interface corresponds to a request of HTTP. The annotation above the method represents the interface address part of the request, and the return type is the return value type of the request.

public interface ApiService {
/ * ** login:* Account + Password *  * @param body  * @return * / @POST("/ny/consumer/login") Observable<BaseResponse<User>> login(@Body RequestBody body); } Copy the code

2. Build a Retrofit instance

Configure the OkHttpClient instance; Set the domain address of the HTTP interface. Add the RxJava2 Network request adapter factory; Add Gson data converter factory;

sRetrofit = new Retrofit.Builder()
        .client(sOkHttpClient)
        .baseUrl(HOST)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
 .build(); Copy the code

3. Generate a dynamic proxy for ApiService

Dynamic proxies are generated with Retrofit to initiate HTTP requests.

sApiService = sRetrofit.create(ApiService.class);
Copy the code

Initiate HTTP requests using dynamic proxies.

getApiService().login(requestBody);
Copy the code

2,

2.1 Construction of Retrofit instances

Retrofit instances are built using the Builder pattern, including

1, okhttp3. Call the Factory

This is OkHttpClient, because OkHttpClient implements okHttp3.call.factory, which is used to initiate requests.

2, Executor

By default, the MainThreadExecutor of Platform.Android implements the Executor interface and the Handler. Post (runnable) operation of the main thread Handler is implemented in the callback. Used to switch the callback result of an asynchronous request from the child thread to the main thread.

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

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

3, List < CallAdapter. Factory >

Adapter factory network request, use the default Platform. Android ExecutorCallAdapterFactory, the network adapter factory adaptation network request is ExecutorCallbackCall.

@Override public @Nullable CallAdapter<? ,? > get(    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if(getRawType(returnType) ! = Call.class) {    return null;
  }
 final Type responseType = Utils.getCallResponseType(returnType);  returnnew CallAdapter<Object, Call<? > > () { @Override public Type responseType() {  return responseType;  }   @Override public Call<Object> adapt(Call<Object> call) {  return new ExecutorCallbackCall<>(callbackExecutor, call);  }  }; } Copy the code

4, List < Converter. The Factory >

Platform.Android OptionalConverterFactory, which uses the default OptionalConverter factory.

2.2. Generate ApiService dynamic proxy and initiate HTTP request

Dynamic Proxy provides very flexible decoupling. Passing in ApiService’s Class object, Proxy provides a static method for creating a dynamic Proxy object. Each method executing a dynamic Proxy instance is replaced with an Invoke method executing an InvocationHandler object.

public <T> T create(final Class<T> service){
}
Copy the code

The invoke method of ServiceMethod is last called from the Invoke method of the InvocationHandler object:

returnloadServiceMethod(method).invoke(args ! = null ? args : emptyArgs);Copy the code

The invoke method is implemented by HttpServiceMethod: the network request adapter ADAPTS OkHttpCall, that is, the network request adapter ADAPTS OkHttpCall, but the return type is adapted by the network request adapter.

@Override ReturnT invoke(Object[] args) {
  return callAdapter.adapt(
      new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
Copy the code

As we know from the configuration of the request network adapter factory above, the default network request adapter is suitable for ExecutorCallbackCall, so the enqueue of ExecutorCallbackCall is used by default for asynchronous network requests:

@Override public void enqueue(final Callback<T> callback) {
  delegate.enqueue(new Callback<T>() {
    @Override public void onResponse(Call<T> call, final Response<T> response) {
      callbackExecutor.execute(new Runnable() {
        @Override public void run() {
 if (delegate.isCanceled()) {  callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));  } else {  callback.onResponse(ExecutorCallbackCall.this, response);  }  }  });  }   @Override public void onFailure(Call<T> call, final Throwable t) {  callbackExecutor.execute(new Runnable() {  @Override public void run() {  callback.onFailure(ExecutorCallbackCall.this, t);  }  });  }  }); } Copy the code

The delegate is the OkHttpCall instance, and the callbackExecutor is the MainThreadExecutor instance. After the OkHttpCall asynchronous callback request, MainThreadExecutor submits the callback task. This task switches the callback result of an asynchronous request from the child thread of the asynchronous request callback to the main thread.

Okhttp3.Call is called to Converter<ResponseBody, T>.

T body = responseConverter.convert(catchingBody);
Copy the code

2.3. RxJava Network Request Adapter Factory

Use the RxJava2CallAdapter as the network request adapter to convert the Call to Observable<Response>.

@Override public Object adapt(Call<R> call) {
  Observable<Response<R>> responseObservable = isAsync
      ? new CallEnqueueObservable<>(call)
      : new CallExecuteObservable<>(call);

Observable<? > observable; if (isResult) {  observable = new ResultObservable<>(responseObservable);  } else if (isBody) {  observable = new BodyObservable<>(responseObservable);  } else {  observable = responseObservable;  }   if(scheduler ! = null) { observable = observable.subscribeOn(scheduler);  }   if (isFlowable) {  return observable.toFlowable(BackpressureStrategy.LATEST);  }  if (isSingle) {  return observable.singleOrError();  }  if (isMaybe) {  return observable.singleElement();  }  if (isCompletable) {  return observable.ignoreElements();  }  return observable; } Copy the code

2.4. Gson Data Converter Factory

Using GsonResponseBodyConverter do data converter, convert ResponseBody to T.

@Override public T convert(ResponseBody value) throws IOException {
  JsonReader jsonReader = gson.newJsonReader(value.charStream());
  try {
    T result = adapter.read(jsonReader);
    if(jsonReader.peek() ! = JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed.");  }  return result;  } finally {  value.close();  } } Copy the code

3, summarize

First, the service interface configures the methods corresponding to the HTTP request and annotates the request address and parameters.

Second, you create a Retrofit instance that is configured with the interface domain name address, the OkHttpClient client, the Executor Executor, the network request adapter factory, the data converter factory, The OkHttpClient client is used to perform network request operations, the Executor Executor is used to perform callbacks that switch the results of asynchronous requests from child threads to the main thread, the network request adapter factory is used to adapt the types of interface method return values, and the data converter factory is used to convert the returned data types.

Third, a dynamic proxy instance of the HTTP service interface is generated using a Retrofit instance. When the dynamic proxy instance performs the request method execution, the Invoke method of the InvocationHandler instance is executed, which is essentially the method that executes the specific network request adapter factory adaptation of the OkHttpCall. Okhttp3.Call enQueue asynchronous network request. After the request is completed, the request response data is converted and returned using a specific data converter factory. Finally, an executor is used to make use of the Handler’s POST (Runnable) to respond to a post-thread switch callback.

Finally, here is the flow chart of Stay: