Converter use of Retrofit2.0

Source: Internet
Author: User

In retrofit, whether to send data or receive data, the most basic is through the okhttp Requestbody and responsebody to achieve, but usually for convenience, we in the custom agreement, The original requestbody or responsebody is not used directly, so in retrofit we need to convert it.

In the definition of the retrofit class, there is a converterfactories list, we can add more than one at build, but note that the order of additions is influential.

Private final list<converter.factory> converterfactories;

In accordance with the logic of retrofit, is the previous match, if the match, ignore the back, direct use.

    int start = Converterfactories.indexof (skippast) + 1;
    for (int i = start, Count = Converterfactories.size (); I < count; i++) {
      converter.factory Factory = Converterfacto Ries.get (i);
      converter<?, requestbody> Converter =
          factory.requestbodyconverter (type, parameterannotations, Methodannotations, this);
      if (converter!= null) {
        //noinspection unchecked return
        (converter<t, requestbody>) converter;
      }
    }

From the source above, you can see that when Factory.requestbodyconverter returns empty, the expression does not match, you can use the next factory.

Therefore, when we customize the converter, we need to make conditional judgments, in accordance with our certain rules to use. Type

Let's take the example of creating Protobuff.

Public final class Protoconverterfactory extends Converter.factory {public static protoconverterfactory create () {
  return new Protoconverterfactory ();
      @Override public Converter<responsebody,?> responsebodyconverter (type type, annotation[] annotations, Retrofit retrofit) {//conditional judgment, if the incoming type is not class, then the match fails if (!) (
    Type instanceof class<?>)) {return null;
    }//conditional judgment, if the incoming type is not a Messagelite implementation class, it also matches the failure class<?> C = (class<?>) type; if (!
    MessageLite.class.isAssignableFrom (c)) {return null;
    } parser<messagelite> Parser;
      try {Field field = C.getdeclaredfield ("PARSER");
    Noinspection Unchecked parser = (parser<messagelite>) field.get (null); catch (Nosuchfieldexception | Illegalaccessexception e) {throw new IllegalArgumentException ("Found a PROTOBUF message but" + C.getnam
    E () + "had no PARSER field."); //Returns a class that implements the converter, REturn new protoresponsebodyconverter<> (parser); @Override public converter<?, requestbody> Requestbodyconverter (type type, annotation[) Parameterannota tions, annotation[] methodannotations, retrofit Retrofit) {//conditional judgment, if the incoming type is not class, then the match fails if (!) (
    Type instanceof class<?>)) {return null; //conditional judgment, if the incoming type is not a Messagelite implementation class, it also matches the failure if (!
    MessageLite.class.isAssignableFrom ((class<?>) type)) {return null;
  Return to New protorequestbodyconverter<> (); }
}

Note in the two generics of convert, the previous type is the object type that is passed in, and the latter is the converted object type.

Final class Protorequestbodyconverter<t extends messagelite> implements Converter<t, requestbody> {
  Private static final mediatype Media_type = Mediatype.parse ("Application/x-protobuf");

  @Override public requestbody Convert (T value) throws IOException {
    byte[] bytes = Value.tobytearray ();
    Return requestbody.create (media_type, bytes);
  }
Final class Protoresponsebodyconverter<t extends messagelite>
    implements Converter<responsebody, t> {
  private Final parser<t> Parser;

  Protoresponsebodyconverter (parser<t> Parser) {
    this.parser = Parser;
  }

  @Override public T Convert (responsebody value) throws IOException {
    try {return
      Parser.parsefrom ( Value.bytestream ());
    } catch (Invalidprotocolbufferexception e) {
      throw new RuntimeException (e);//Despite extending IOException, this is DA Ta mismatch.
    } finally {
      value.close ();}}}
Annotation

In some cases, it is not enough to judge by type alone, and additional parameters are required. Then we can take advantage of the following two parameters.

Let's look at the Requestbodyconverter function signature first.

Public converter<?, requestbody> Requestbodyconverter (type type,
        annotation[] parameterannotations, Annotation[] methodannotations, retrofit retrofit)

Obviously, parameterannoatations refers to annotations that define the parameters of an interface. such as the following mytype:

@GET ("applist/mini-appcenter/")
    call<miniappcenterpojo> Getminiapp (@Query ("offsets") @TypeString String offsets);

The annotation defined on the method is Methodannotations

     @TypeString
    @GET ("applist/mini-appcenter/")
    call<miniappcenterpojo> Getminiapp (@Query ("offsets") String offsets);

We can make a custom converter match by judging the annotations.

@Documented
@Target (PARAMETER)
@Retention (RUNTIME) public
@interface typestring{
}
public class Stringconverterfactory extends Converter.factory {@Override public converter<responsebody,?> Responsebodyconverter (type type, annotation[] annotations, Re Trofit Retrofit) {if (!) (
        Type instanceof class<?>)) {return null;
                for (Annotation annotation:annotations) {if (Annotation instanceof typestring) {
            return new Stringresponseconverter ();
    } return null;
                                                          @Override public converter<?, requestbody> Requestbodyconverter (type type,
        Annotation[] parameterannotations, annotation[] methodannotations, retrofit retrofit) { if (!) (
        Type instanceof class<?>)) {return null;
           For (Annotation Annotation:p arameterannotations) {if (Annotation instanceof typestring) {     return new Stringrequestconverter ();
    } return null;
        public static class Stringresponseconverter implements Converter<responsebody, string> {@Override
        Public String CONVERT (responsebody value) throws IOException {return value.string (); } public static class Stringrequestconverter implements Converter<string, requestbody> {@Overrid E public requestbody convert (String value) throws IOException {return requestbody.create (MEDIATYPE.PA
        RSE ("Application/octet-stream"), value); }
    }
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.