美文网首页
Retrofit源码 - CallAdapter和Convert

Retrofit源码 - CallAdapter和Convert

作者: YocnZhao | 来源:发表于2019-02-15 16:59 被阅读0次

接上篇Retrofit的简单解析,这篇写个最简单的CallAdapter跟Converter的例子。
接口找了个免费的天气接口
首先是Converter,上篇文章后面我们知道GsonConverterFactory是cover到了所有的responseType,我们自定义的写了两种:String和Weather,Weather是我自定义的数据bean。
首先看调用:

public class RetrofitFactory {
    static Retrofit retrofit;
    static ApiService apiService;

    public static ApiService getInstance() {
        //https://restapi.amap.com/v3/weather/weatherInfo?key=5326a9f59587393b549f3cffefa0459b&city=110000&output=json&extensions=base
        if (apiService == null) {
            retrofit = new Retrofit.Builder()
                    .addConverterFactory(new MyConverterFactory())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(new MyCallAdapterFactory())
                    .baseUrl("https://restapi.amap.com/v3/weather/")
                    .build();
            apiService = retrofit.create(ApiService.class);
        }
        return apiService;
    }
}
public class TestRetrofit {
    public static void test() {
        retrofitGetWeather();
    }

    public static void retrofitGetWeather() {
        Call<Weather> call = RetrofitFactory.getInstance().getWeather("5326a9f59587393b549f3cffefa0459b", "110000", "json", "base");
        call.enqueue(new Callback<Weather>() {
            @Override
            public void onResponse(Call<Weather> call, Response<Weather> response) {
                LogUtil.Companion.d("" + response.body().toString());
            }

            @Override
            public void onFailure(Call<Weather> call, Throwable t) {
            }
        });

    }

MyConverterFactory:

public class MyConverterFactory extends Converter.Factory {
    @Nullable
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if (type == String.class) {
            return new StringConverter();
        } else if (type == Weather.class) {
            return new WeatherConverter();
        }
        return null;
    }

    class StringConverter implements Converter<ResponseBody, String> {
        @Nullable
        @Override
        public String convert(ResponseBody value) throws IOException {
            return value.string();
        }
    }

    class WeatherConverter implements Converter<ResponseBody, Weather> {
        @Nullable
        @Override
        public Weather convert(ResponseBody value) throws IOException {
            Weather weather = new Weather();
            weather.setCount(100);
            weather.setStatus(999);
            weather.setInfo("I'm A Fake Weather create by MyConverterFactory!");
            Exception e = new Exception("this is a exception log for print");
            e.printStackTrace();
            return weather;
        }
    }

上面的代码我们可以看到,首先判断了类型,我只管String和Weather类型,其他类型都返回null,返回null表示这个类型我处理不了,retrofit会继续找下一个factory去处理,这个自定义converter其实是把结果请求下来,并创建了一个假的Weather返回给了调用者。这个Weather就是我们调用的时候需要返回的Weather,就是上面这里要返回的Weather
Call<Weather> call = RetrofitFactory.getInstance().getWeather("5326a9f59587393b549f3cffefa0459b", "110000", "json", "base");

MyCallAdapterFactory:

public class MyCallAdapterFactory extends CallAdapter.Factory {
    @Nullable
    @Override
    public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
        for (Annotation a : annotations) {
            LogUtil.Companion.d("Annotation->" + a.toString());
        }
        Type wrapperType = getParameterUpperBound(0, (ParameterizedType) returnType);
        LogUtil.Companion.d("MyCallAdapterFactory->" + returnType
                + " getRawType->" + getRawType(returnType)
                + " Type->" + wrapperType);
        if (wrapperType == String.class) {
            return new StringCallAdapter();
        } else if (wrapperType == Weather.class) {
            Exception e = new Exception("call Weather print");
            e.printStackTrace();
            return new WeatherCallAdapter();
        }
        return null;
    }

    class StringCallAdapter implements CallAdapter<String, String> {

        @Override
        public Type responseType() {
            return String.class;
        }

        @Override
        public String adapt(Call<String> call) {
            try {
                return call.execute().body();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
        }
    }

    class WeatherCallAdapter implements CallAdapter<String, retrofit2.Call> {

        @Override
        public Type responseType() {
            return Weather.class;
        }

        @Override
        public retrofit2.Call adapt(Call<String> call) {
            LogUtil.Companion.d("yocn weather->" + call.request().toString());
            return call;
        }
    }

其实这个CallAdapter里面什么都没有做,只是做了个打印,进来的Call原样子返回了回去。其实就是类似Retrofit里面的DefaultCallAdapterFactory,它也是什么斗殴没有做,直接把Call返回了回去。
要注意的是getRawType方法跟getParameterUpperBound方法,看打印可以看到retrofit2.Call<retrofit.Weather>
getRawType拿到的是retrofit2.Call
getParameterUpperBound返回的是retrofit.Weather
我们需要判断是不是Weather

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }

    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return call;
      }
    };
  }
}

可以执行的例子Github传送门

相关文章

网友评论

      本文标题:Retrofit源码 - CallAdapter和Convert

      本文链接:https://www.haomeiwen.com/subject/iuopeqtx.html