Android network request frame used Retrofit 1 ------

In "Android web request frame ----- Retrofit (dynamic proxy mode)" , a brief introduction about the realization of the principles underlying Retrofit, this section mainly introduce the use of Retrofit.

1.Retrofit advantage of
API is simple, highly decoupling using annotations, support for multiple parsers, support RxJava.

2.
After introducing these advantages Retrofit from the use of perspective about how specific advantage is achieved.

(1) before use, requires some configuration, added Retrofit dependent libraries, OkHttp dependent libraries and data parsing library

implementation 'com.squareup.retrofit2:retrofit:2.7.1'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.squareup.retrofit2:converter-gson:2.7.1'

(2) create an interface, set the request parameter
First we create an entity class the DataBean, is generally created based on the data type returned, this and general data analysis is the same as when using Gson or fastjson parse JSON data, created the same entity class;

public interface UpdateService {
    @GET("getAppConfig.php")
    public Call<DataBean> update(
            //内部是请求的参数
            @Query("appid") String appid
    );
}

Then create an interface, we want to specify the address of the request, and the request parameters.

Some of the parameters used to comment:

@GET get request
@POST post request
@Path Dynamic URL instead of
@Query Parameters to be passed
@QueryMap Multi-parameter (probably over 10)
@Body Add entity class object

(3) Create Retrofit object, setting data analyzer, performing network requests, to obtain the response data

Retrofit retrofit = new Retrofit.Builder().baseUrl(Constant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create()).build();
        UpdateService updateService = retrofit.create(UpdateService.class);
        Call<DataBean> call = updateService.update("ceshiqianggeng777");
        call.enqueue(new Callback<DataBean>() {
            @Override
            public void onResponse(Call<DataBean> call, Response<DataBean> response) {
                //请求成功,返回是一个封装为DataBean的响应
                String url = response.body().getUrl();
                Log.e("TAG","Url ===== "+url);
            }

            @Override
            public void onFailure(Call<DataBean> call, Throwable t) {
                //请求失败
            }
        });

After the run, it has successfully acquired DataBean response url field.

2020-02-06 17:16:47.147 2407-2407/com.example.myapplication E/TAG: Url ===== https://andownload.yyguokang120.com/bxvip/androidapk/152caizy01.apk

Briefly summarize contrast on Retrofit of use and OkHttp of:
(1) When using OkHttp process data acquired data need to manually parse, like JSON data, we need to go to create the entity classes based on JSON data, and then get the data, although not difficult, but also requires several steps; Retrofit in response, the entity will be directly to this class encapsulates response, no need to manually parse.
(2) I am not here to update the UI, like when using OkHttp, access to the data needed to get the data back to the main thread to update the UI, but does not require such use Retrofit, directly in onResponsethe UI update

 @Override
public void onResponse(Call<DataBean> call, Response<DataBean> response) {
       //请求成功,返回是一个封装为DataBean的响应
       String url = response.body().getUrl();
       Log.e("TAG","Url ===== "+url);
       //可直接在此更新UI
   }

3. Dynamic url arranged
in a network request, the base_url not change, but may become parameters of the request, so if the interface class, the write request parameters @GET dead behind, does not have the scalability, so dynamic configuration url, You can use @Path

Suppose that I GET request may request that the current interface and other interfaces, then this parameter can be "getAppConfig.php" as the field value of the Path, then enclosed by {};

public interface UpdateService {
    @GET("{path}")
    public Call<DataBean> update(
            //内部是请求的参数
            @Path("path") String path,
            @Query("appid") String appid
    );
}

And just getting to do comparison

public interface UpdateService {
    @GET("getAppConfig.php")
    public Call<DataBean> update(
            //内部是请求的参数
            @Query("appid") String appid
    );
}
 Call<DataBean> call = updateService.update("getAppConfig.php","ceshiqianggeng777");

In fact, both requests are the same url:
baseurl / getAppConfig.php AppID = ceshiqianggeng777?

If you previously used are OkHttp, then the first time you use Retrofit, there is no love the feeling of it?

4. custom type conversion

Before Retrofit when using the data parser is GsonConverterFactory, this internal parser source code:

public final class GsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
//这个方法目前没用到,因为我们没有使用post请求。
  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

This data parser internally new Gson (), and in response to the data acquired, i.e. when ResponseBody, convert it to the JavaBean, and this process is responseBodyConvertercarried out in the process, after obtaining the current data type, the final It returns an GsonResponseBodyConverterObject

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @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();
    }
  }
}

In the GsonResponseBodyConvertermethods, the method has a convert, after the data stream is acquired ResponseBody utilizing Gson this data stream is converted to a corresponding type of JavaBean.

This is also when we use the Retrofit of the response at the time of acquisition, as we have a good package in response to the JavaBean.

If in actual use, in addition to using conversion Gson outside, for example, we want to convert the time of type String type of data, so we can customize the data parser.

public class DateConvertFactory extends Converter.Factory {
    //将时间类型转换为String 类型
    @Override
    public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if(type == Date.class){
            //就去进行类型转换
            return new DateConvert();
        }
        return super.stringConverter(type, annotations, retrofit);
    }

    private class DateConvert implements Converter<Date, String> {
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        @Override
        public String convert(Date value) throws IOException {
            return sdf.format(value);
        }
    }
    
    public static DateConvertFactory create(){
        return new DateConvertFactory();
    }
}

In fact, this custom data parser is now thought Gson data parser is the same, GsonConverterFactory inherited from Converter.Factory, then inherit the parent class, in addition can override toString, as well as
Here Insert Picture Description
these data parser Gson there are reflected.

In this self-defined data analysis, but also inherited the Converter.Factory, which overrides the stringConvertermethod, which can be converted to a type of type String, if the judgment is Date type, then go type conversion.

Type conversion is to achieve Converter<Date, String>the interface, will be converted to Date String, rewrite convert method.

5.POST request
when using OkHttp, if the use of post request, you need to create a data request carrying body RequsetBody request, then Retrofit using POST parameter @Field need to use annotations and @FormUrlEncoded.

public interface UpdateService {
    @GET("{path}")
    public Call<DataBean> update(
            //内部是请求的参数
            @Path("path") String path,
            @Query("appid") String appid
    );

    @POST("getAppConfig.php")
    @FormUrlEncoded
    public Call<DataBean> updateForPost(
            //请求的参数
            @Field("appid") String appid
    );
}

And compared to the GET request, only when the request for change @Query @Field; occurs in nature, but great changes. @Query In use, the data request is spliced ​​directly behind url, @ Field requested data equivalent thereof, first transmission request header and then sends the request body, and more secure.

Well, that's simple to use Retrofit, the follow-up will continue to update!

Published 15 original articles · won praise 5 · Views 628

Guess you like

Origin blog.csdn.net/qq_33235287/article/details/104197520