探索Android开源框架 - 2. Retrofit使用及源码解析

  • Retrofit是目前Android最优秀的网络封装框架,是对OkHttp网络请求库的封装
  • App应用程序通过Retrofit请求网络,实际上是使用Retrofit接口层封装请求参数,之后由OkHttp完成后续的请求操作;服务器数据返回后,OkHttp将原始的结果交给Retrofit,根据用户需求对结果进行解析;

使用

简单使用

添加依赖
  • retrofit2内置了OkHttp,所以无需再单独添加OkHttp依赖了
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
创建Retrofit实例
val baseUrl = "https://api.github.com/"
val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(60, TimeUnit.SECONDS)
    .writeTimeout(90, TimeUnit.SECONDS)
    .build()
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .client(okHttpClient)
    .build()
创建返回数据的类
class RepoList {
    @SerializedName("items") val items:List = emptyList()
}

data class Repo(
    @SerializedName("id") val id: Int,
    @SerializedName("name") val name: String,
    @SerializedName("description") val description: String,
    @SerializedName("stargazers_count") val starCount: String,
)
创建网络请求接口
interface ApiService {
    @GET("search/repositories?sort=stars&q=Android")
    fun searRepos(@Query("page") page: Int, @Query("per_page") perPage: Int): Call
}
创建网络请求接口实例
val apiService = retrofit.create(ApiService::class.java)
调用接口实例方法获取Call
val call = apiService.searRepos(1, 5)
发送网络请求
1.同步请求
val response: Response = call.execute()
if (response.isSuccessful) {
    val repo = response.body()
    LjyLogUtil.d(repo.toString())
} else {
    LjyLogUtil.d("code=${response.code()}, msg=${response.message()}")
    LjyLogUtil.d(IOException("Unexpected code $response").message)
}
2.异步请求
call.enqueue(object : Callback {
    override fun onResponse(call: Call, result: Response) {
        if (result.body() != null) {
            val repoList: RepoList = result.body()!!
            for (it in repoList.items) {
                LjyLogUtil.d("${it.name}_${it.starCount}")
                LjyLogUtil.d(it.description)
            }
        }
    }

    override fun onFailure(call: Call, t: Throwable) {
        LjyLogUtil.d("onFailure:${t.message}")
    }
})

注解类型

1. 网络请求方法
@GET, @POST, @PUT, @DELETE, @HEAD, @PATCH,@OPTIONS
  • 分别对应 HTTP中的网络请求方式
  • 注解的value属性用来设置相对/完整url, 如果是完整url则可以覆盖创建Retrofit实例时的baseUrl
  • Retrofit把网络请求的URL分成了两部分设置,一是创建Retrofit实例时设置的baseUrl,另一半是 网络请求方法注解的value设置或@Url中设置的部分,
@GET("api/items")
fun getRepos(): Call

@GET("https://api.github.com/api/items")
fun getRepos(): Call
@HTTP
  • 替换以上注解的作用 及 更多的功能拓展
/**
 * method:网络请求的方法(区分大小写)
 * path:网络请求地址路径
 * hasBody:是否有请求体
 */
@HTTP(method = "GET", hasBody = false)
fun getRepos(@Url url: String):  Call

@HTTP(method = "GET", path = "api/items/{userId}", hasBody = false)
fun getRepos2(@Path("userId") userId: String) :  Call
2. 标记
@FormUrlEncoded
  • 表示请求体(RequestBody)是Form表单
@FormUrlEncoded
@POST("api/search")
fun searchRepo( @Field("name") repoName:String): Call
@Multipart
  • 表示请求体是一个支持文件上传的Form表单
  • 具体使用见下面的@Part部分
@Streaming
  • 表示返回的数据以流的形式返回,适用于返回数据较大的场景(若没有使用该注解,默认是吧数据全部载入内存中)
@Streaming
@GET
fun downloadFile(@Url url: String?): Call
3. 网络请求参数
@Path
  • URL地址的缺省值
@GET("api/items/{userId}/repos")
fun getItem(@Path("userId") userId: String): Call
//在发起请求时, {userId} 会被替换为方法的参数 userId(被@Path注解的参数)
@Url
  • 直接传入一个请求的url,和@GET,@POST等注解的value属性设置url类似,但是通过参数传入显然更灵活一点
@FormUrlEncoded
@POST("api/search")
fun searchRepo(@Url url: String, @Field("name") repoName: String): Call
@Header & @Headers
  • 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
  • 使用方式:@Header作用于方法的参数;@Headers作用于方法
@Streaming
@GET
fun downloadFile(@Header("RANGE") start:String , @Url url: String?): Call

@Headers("Content-Type: application/json;charset=UTF-8")
@POST("api/search")
fun searchRepo2(@Body params: Map): Call
  • 添加header还可以通过上一篇介绍过的okHttp拦截器实现
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(object : Interceptor{
        override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
            val request=chain.request().newBuilder()
                .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                .addHeader("Accept-Encoding", "gzip, deflate")
                .addHeader("Connection", "keep-alive")
                .addHeader("Accept", "*/*")
                .addHeader("Cookie", "add cookies here")
                .build()
            return chain.proceed(request)
        }
    })
    .build()
@Query & @QueryMap
  • 用于 @GET 方法的查询参数
@GET("search/repositories?sort=stars&q=Android")
fun searRepos(@Query("page") page: Int, @Query("per_page") perPage: Int): Call

@GET("search/repositories?sort=stars&q=Android")
fun searRepos(@QueryMap params: Map): Call
@Field & @FieldMap
  • 发送 Post请求 时提交请求的表单字段,与 @FormUrlEncoded 注解配合使用
@FormUrlEncoded
@POST("api/search")
fun searchRepo(@Url url: String, @Field("name") repoName: String): Call

@FormUrlEncoded
@POST("api/search")
fun searchRepo(@Url url: String, @FieldMap params: Map): Call
@Part & @PartMap
  • 发送 Post请求 时提交请求的表单字段, 与 @Multipart 注解配合使用
  • 与@Field的区别:功能相同,但携带的参数类型更加丰富,包括数据流,所以适用于 有文件上传 的场景
@POST("upload/imgFile")
@Multipart
fun uploadImgFile(
    @Part("userId") userId: RequestBody?,
    @PartMap partMap: Map,
    @Part("file") file: MultipartBody.Part
): Call

@Multipart
@POST("upload/files")
fun uploadFiles(
    @Part("userId") userId: RequestBody?,
    @Part files: List
): Call

//使用:
val userId: RequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), "1111")

val paramsMap: MutableMap = HashMap()
paramsMap["userId"] = RequestBody.create(MediaType.parse("text/plain"), "123456")
paramsMap["userName"] = RequestBody.create(MediaType.parse("text/plain"), "jinYang")
paramsMap["taskName"] = RequestBody.create(MediaType.parse("text/plain"), "新建派单")

val imgFile=File(externalCacheDir, "ljy.jpg")
val requestFile: RequestBody =
    RequestBody.create(MediaType.parse("multipart/form-data"),imgFile )

val partFile = MultipartBody.Part.createFormData("imageUrl", imgFile.name, requestFile)

apiService.uploadImgFile(userId,paramsMap,partFile)

val imgFile1=File(externalCacheDir, "ljy1.jpg")
val imgFile2=File(externalCacheDir, "ljy2.jpg")
val imgFile3=File(externalCacheDir, "ljy3.jpg")
val imageFiles= arrayOf(imgFile1,imgFile2,imgFile3)
val parts = ArrayList(imageFiles.size)
for (i in imageFiles.indices) {
    val file: File = imageFiles[i]
    parts[i] = MultipartBody.Part.createFormData(
        "file_$i", file.name, RequestBody.create(
            MediaType.parse("image/*"), file
        )
    )
}

apiService.uploadFiles(userId,parts)
@Body
  • 以 Post方式 传递 自定义数据类型 给服务器,如果提交的是一个Map,那么作用相当于 @Field
@Headers("Content-Type: application/json;charset=UTF-8")
@POST("api/add")
fun addRepo(@Body repo: Repo): Call

@Headers("Content-Type: application/json;charset=UTF-8")
@POST("api/add")
fun addRepo2(@Body params: Map): Call

@Headers("Content-Type: application/json;charset=UTF-8")
@POST("api/add")
fun addRepo3(@Body body: RequestBody): Call

@FormUrlEncoded
@POST("api/add")
fun addRepo4(@Body body: FormBody): Call

//使用:
val repo = Repo(1, "name", "info", "20")
apiService.addRepo(repo)

val map: MutableMap = HashMap()
map["key"] = "value"
apiService.addRepo2(map)

val body: RequestBody = RequestBody
    .create(MediaType.parse("application/json; charset=utf-8"), repo.toString())
apiService.addRepo3(body)

val formBody = FormBody.Builder()
    .add("key", "value")
    .build()
apiService.addRepo4(formBody)

数据解析器 & 请求适配器

  • Retrofit支持多种数据解析方式和网络请求适配器,使用时需要在Gradle添加依赖
数据解析器
  • 默认情况下Retrofit只支持将HTTP的响应体转换换为Call,有了Converter就可以把ResponseBody替换成其他类型,
    如我们常用的GsonConverterFactory,下面列出官方给我们提供的Converter;
1. 添加依赖
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'//Gson的支持 [常用] [可选]
implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0'//simplexml的支持 [可选]
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0'//jackson的支持 [可选]
implementation 'com.squareup.retrofit2:converter-protobuf:2.9.0'//protobuf的支持 [可选]
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'//moshi的支持 [可选]
implementation 'com.squareup.retrofit2:converter-wire:2.9.0'//wire的支持 [可选]
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'//String的支持 [可选]
2. 创建Retrofit实例时添加
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create())
    .addConverterFactory(JacksonConverterFactory.create())
    .addConverterFactory(SimpleXmlConverterFactory.create())
    .addConverterFactory(ProtoConverterFactory.create())
    .addConverterFactory(ScalarsConverterFactory.create())
    .build()
3. 自定义Converter
  • 自定义之前我们先来看看官方是如何实现的, 以平时最常用的GsonConverterFactory为例
//继承Converter.Factory
public final class GsonConverterFactory extends Converter.Factory {
  //静态的create方法
  public static GsonConverterFactory create() {
    return create(new Gson());
  }


  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;
  }

  //重写responseBodyConverter方法,将响应体交给GsonResponseBodyConverter处理
  @Override
  public Converter responseBodyConverter(
      Type type, Annotation[] annotations, Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

  //重写requestBodyConverter方法,将请求体交给GsonRequestBodyConverter处理
  @Override
  public Converter requestBodyConverter(
      Type type,
      Annotation[] parameterAnnotations,
      Annotation[] methodAnnotations,
      Retrofit retrofit) {
    TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

//处理响应体的Converter,实现Converter接口
final class GsonResponseBodyConverter implements Converter {
  private final Gson gson;
  private final TypeAdapter adapter;

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

   //重写convert方法,将ResponseBody通过Gson转为自定义的数据模型类
  @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();
    }
  }
}

//处理请求体的Converter,实现Converter接口
final class GsonRequestBodyConverter implements Converter {
  private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
  private static final Charset UTF_8 = Charset.forName("UTF-8");

  private final Gson gson;
  private final TypeAdapter adapter;

  GsonRequestBodyConverter(Gson gson, TypeAdapter adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

   //重写convert方法,通过Gson将自定义的数据模型类转换为RequestBody
  @Override
  public RequestBody convert(T value) throws IOException {
    Buffer buffer = new Buffer();
    Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
    JsonWriter jsonWriter = gson.newJsonWriter(writer);
    adapter.write(jsonWriter, value);
    jsonWriter.close();
    return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
  }
}

  • 那么我们来自己试试吧:
  • 例1:返回格式为Call
//1. 自定义StringConverter,实现Converter
class StringConverter : Converter {
    companion object {
        val INSTANCE = StringConverter()
    }

    @Throws(IOException::class)
    override fun convert(value: ResponseBody): String {
        return value.string()
    }
}

//2. 自定义StringConverterFactory,用来向Retrofit注册StringConverter
class StringConverterFactory : Converter.Factory() {
    companion object {
        private val INSTANCE = StringConverterFactory()
        fun create(): StringConverterFactory {
            return INSTANCE
        }
    }

    // 只实现从ResponseBody 到 String 的转换,所以其它方法可不覆盖
    override fun responseBodyConverter(
        type: Type,
        annotations: Array?,
        retrofit: Retrofit?
    ): Converter? {
        return if (type === String::class.java) {
            StringConverter.INSTANCE
        } else null
        //其它类型不处理,返回null
    }
}

3. 使用
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    // 自定义的Converter一定要放在官方提供的Converter前面
    //addConverterFactory是有先后顺序的,多个Converter都支持同一种类型,只有第一个才被使用
    .addConverterFactory(StringConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .build()
  • 例2:ResponseBody转换为Map
class MapConverterFactory : Converter.Factory() {
    companion object {
        fun create(): MapConverterFactory {
            return MapConverterFactory()
        }
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array,
        retrofit: Retrofit
    ): Converter {
        return MapConverter()
    }

    class MapConverter : Converter> {
        @Throws(IOException::class)
        override fun convert(body: ResponseBody): Map {
            val map: MutableMap = HashMap()
            val content = body.string()
            val keyValues = content.split("&").toTypedArray()
            for (i in keyValues.indices) {
                val keyValue = keyValues[i]
                val splitIndex = keyValue.indexOf("=")
                val key = keyValue.substring(0, splitIndex)
                val value = keyValue.substring(splitIndex + 1, keyValue.length)
                map[key] = value
            }
            return map
        }
    }
}
请求适配器
  • Converter是对于Call中T的转换,而CallAdapter则可以对Call转换,下面列出官方给我们提供的CallAdapter;
1. 添加依赖
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'//RxJava支持 [常用] [可选]
implementation 'com.squareup.retrofit2:adapter-java8:2.9.0'//java8支持 [可选]
implementation 'com.squareup.retrofit2:adapter-guava:2.9.0'//guava支持 [可选]
2. 创建Retrofit实例时添加
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addCallAdapterFactory(Java8CallAdapterFactory.create())
    .addCallAdapterFactory(GuavaCallAdapterFactory.create())
    .build()
3. 自定义CallAdapter
  • 同样的我们来看看官方的RxJava2CallAdapterFactory是如何实现的
//适配器工厂类,继承CallAdapter.Factory
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
  //静态的create方法
  public static RxJava2CallAdapterFactory create() {
    return new RxJava2CallAdapterFactory(null, false);
  }

  ...
  //Rxjava的调度器scheduler
  private final @Nullable Scheduler scheduler;
  private final boolean isAsync;
  //构造方法
  private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
    this.scheduler = scheduler;
    this.isAsync = isAsync;
  }

  //重写get方法,返回RxJava2CallAdapter
  @Override
  public @Nullable CallAdapter get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    Class rawType = getRawType(returnType);
    ...
    return new RxJava2CallAdapter(
        responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);
  }
}

//适配器类,实现CallAdapter接口
final class RxJava2CallAdapter implements CallAdapter {
  private final Type responseType;
  RxJava2CallAdapter(Type responseType,....){this.responseType = responseType;....}
  ...
  //重写responseType方法
  @Override
  public Type responseType() {
    return responseType;
  }

  //重写adapt方法,通过 RxJava2 将Call转换为Observable
  @Override
  public Object adapt(Call call) {
    Observable> 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 RxJavaPlugins.onAssembly(observable);
  }
}

  • 然后我们自己试试搞一个
//1. 自定义Call
class LjyCall(private val call: Call) {
    @Throws(IOException::class)
    fun get(): T? {
        return call.execute().body()
    }
}
//2. 自定义CallAdapter
class LjyCallAdapter(private val responseType: Type) : CallAdapter {
    override fun responseType(): Type {
        return responseType
    }

    override fun adapt(call: Call): Any {
        return LjyCall(call)
    }
}
//3. 自定义CallAdapterFactory
class LjyCallAdapterFactory : CallAdapter.Factory() {
    companion object {
        private val INSTANCE = LjyCallAdapterFactory()
        fun create(): LjyCallAdapterFactory {
            return INSTANCE
        }
    }

    override fun  get(
        returnType: Type,
        annotations: Array,
        retrofit: Retrofit
    ): CallAdapter? {
        // 获取原始类型
        val rawType = getRawType(returnType)
        if (rawType == LjyCall::class.java && returnType is ParameterizedType) {
            val callReturnType = getParameterUpperBound(0, returnType)
            return LjyCallAdapter(callReturnType)
        }
        return null
    }
}
//4. 使用
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    //也是放到前面,有先后顺序
    .addCallAdapterFactory(LjyCallAdapterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

源码解析

  • 源码地址: square/retrofit

Retrofit & Builder

Builder的构造方法
  • Retrofit实例通过Builder(建造者)模式创建, 那么我们来看看Builder的构造方法
public static final class Builder {
    //平台类型对象
    private final Platform platform;
    //网络请求工厂,默认使用OkHttpClient, 生产网络请求器(Call)
    private @Nullable okhttp3.Call.Factory callFactory;
    //url的基地址,注意这里的类型是HttpUrl,而非String
    private @Nullable HttpUrl baseUrl;
    //数据转换器工厂集合
    private final List converterFactories = new ArrayList<>();
    //适配器工厂集合
    private final List callAdapterFactories = new ArrayList<>();
    //回调方法执行器,在 Android 上默认是封装了 handler 的 MainThreadExecutor
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;
    public Builder() {
      this(Platform.get());
    }
    Builder(Platform platform) {
      this.platform = platform;
    }
    ...
}
  • 可以看到构造函数中platform是通过Platform.get()获取的,那么来看看Platform.get()代码的实现,
class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }
  ...
}
  • 很明显我们需要的是Android的实现,它的defaultCallbackExecutor返回封装了Handler的MainThreadExecutor,
    其作用是可以从工作线程切换到UI线程
static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

   ...

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

      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
}
Builder.build()
  • 生成Retrofit实例最后需要调用build, 那么我们来看看该方法的实现
public Retrofit build() {

      //可以看到baseUrl是必须设置的
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //callFactory 默认使用OkHttpClient
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        //这里就是对应上面Android的defaultCallbackExecutor,返回封装了Handler的MainThreadExecutor,
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      //数据解析器的集合:
      // Make a defensive copy of the adapters and add the default Call adapter.
      List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      //适配器的集合:
      // Make a defensive copy of the converters.
      List 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());

      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
}
  • 上面可以看到baseUrl是必须设置的,那么再来看看其有何要求呢
public Builder baseUrl(String baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl));
}

public Builder baseUrl(HttpUrl baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    List pathSegments = baseUrl.pathSegments();
    //如果host后面由路径,则必须以’/‘结尾
    if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
      throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
    }
    this.baseUrl = baseUrl;
    return this;
}

  /**
   * Returns a list of path segments like {@code ["a", "b", "c"]} for the URL {@code
   * http://host/a/b/c}. This list is never empty though it may contain a single empty string.
   *
   * 

* * * * *
URL{@code pathSegments()}
{@code http://host/}{@code [""]}
{@code http://host/a/b/c"}{@code ["a", "b", "c"]}
{@code http://host/a/b%20c/d"}{@code ["a", "b c", "d"]}
*/ public List pathSegments() { return pathSegments; }
  • 上面build方法中说了,callFactory 默认使用OkHttpClient,可能从命名上看并不是一个类型,
    但是如果我们看看OkHttpClient源码就会发现它实现了Call.Factory;
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
    ...
}
Retrofit的构造方法
  • 看过了Builder再来看看我们的主角Retrofit,先来看看其变量和构造方法
public final class Retrofit {
   //网络请求配置对象的集合(对网络请求接口中方法注解进行解析后得到的对象)
  private final Map> serviceMethodCache = new ConcurrentHashMap<>();

   //下面几个在Builder中都有过介绍了
  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List converterFactories;
  final List callAdapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;

  Retrofit(
      okhttp3.Call.Factory callFactory,
      HttpUrl baseUrl,
      List converterFactories,
      List callAdapterFactories,
      @Nullable Executor callbackExecutor,
      boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
  ...
}
Retrofit的create方法
  • 使用中我们创建了retrofit实例后,会调用其create方法生成接口的动态代理对象,代码如下
public  T create(final Class service) {
    validateServiceInterface(service);
    return (T)
        //通过动态代理创建接口的实例
        Proxy.newProxyInstance(
            //参数1:classLoader
            service.getClassLoader(),
            //参数2:接口类型数组
            new Class[] {service},
            //参数3:实现了InvocationHandler的代理类
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
}
  • 可以看到其invoke方法中最后调用了loadServiceMethod方法,其代码如下,就是将method解析为ServiceMethod,并加入到serviceMethodCache中缓存
ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      //先在缓存map中获取
      result = serviceMethodCache.get(method);
      if (result == null) {
        //取不到新建一个并加入缓存
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
}
  • 上面代码的解析工作实际是调用 ServiceMethod.parseAnnotations,通过 RequestFactory 完成对注解的解析的
abstract class ServiceMethod {
  static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
    Type returnType = method.getGenericReturnType();
    ...
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }
+
  abstract @Nullable T invoke(Object[] args);
}
  • 那么再来看看RequestFactory.parseAnnotations中干了点啥吧
final class RequestFactory {
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
        return new Builder(retrofit, method).build();
    }
    ...
    static final class Builder {
        Builder(Retrofit retrofit, Method method) {
          this.retrofit = retrofit;
          this.method = method;
          //获取网络请求方法的注解:如@GET,@POST@HTTP
          this.methodAnnotations = method.getAnnotations();
          //获取网络请求方法参数的类型
          this.parameterTypes = method.getGenericParameterTypes();
          //获取网络请求参数的注解,如@Url,@Path,@Query等
          this.parameterAnnotationsArray = method.getParameterAnnotations();
        }

        //build方法
        RequestFactory build() {
          //解析网络请求方法的注解
          for (Annotation annotation : methodAnnotations) {
            parseMethodAnnotation(annotation);
          }
          ...
          //解析网络请求方法参数的类型和注解
          int parameterCount = parameterAnnotationsArray.length;
          parameterHandlers = new ParameterHandler[parameterCount];
          for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
            parameterHandlers[p] =
                parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
          }
          ...
          return new RequestFactory(this);
        }

        //解析网络请求方法的注解,看到下面的是不是很眼熟,有点豁然开朗了
        private void parseMethodAnnotation(Annotation annotation) {
          if (annotation instanceof DELETE) {
            parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
          } else if (annotation instanceof GET) {
            parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
          } else if (annotation instanceof HEAD) {
            parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
          } else if (annotation instanceof PATCH) {
            parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
          } else if (annotation instanceof POST) {
            parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
          } else if (annotation instanceof PUT) {
            parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
          } else if (annotation instanceof OPTIONS) {
            parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
          } else if (annotation instanceof HTTP) {
            HTTP http = (HTTP) annotation;
            parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
          } else if (annotation instanceof retrofit2.http.Headers) {
            String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
            if (headersToParse.length == 0) {
              throw methodError(method, "@Headers annotation is empty.");
            }
            headers = parseHeaders(headersToParse);
          } else if (annotation instanceof Multipart) {
            if (isFormEncoded) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isMultipart = true;
          } else if (annotation instanceof FormUrlEncoded) {
            if (isMultipart) {
              throw methodError(method, "Only one encoding annotation is allowed.");
            }
            isFormEncoded = true;
          }
        }

        //解析网络请求方法参数的类型和注解
        private @Nullable ParameterHandler parseParameter(
            int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
          ParameterHandler result = null;
          if (annotations != null) {
            for (Annotation annotation : annotations) {
              ParameterHandler annotationAction =
                  parseParameterAnnotation(p, parameterType, annotations, annotation);
              ...
              result = annotationAction;
            }
          }
          ...
          return result;
        }

        //解析网络请求方法参数的类型和注解
        @Nullable
        private ParameterHandler parseParameterAnnotation(
            int p, Type type, Annotation[] annotations, Annotation annotation) {
              //判断参数的注解注解
              if (annotation instanceof Url) {
                ...
                gotUrl = true;
                //判断参数的类型
                if (type == HttpUrl.class
                    || type == String.class
                    || type == URI.class
                    || (type instanceof Class && "android.net.Uri".equals(((Class) type).getName()))) {
                  return new ParameterHandler.RelativeUrl(method, p);
                }
                ...
              } else if (annotation instanceof Path) {
                ...
                gotPath = true;
                Path path = (Path) annotation;
                String name = path.value();
                validatePathName(p, name);
                Converter converter = retrofit.stringConverter(type, annotations);
                return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
              } else if (annotation instanceof Query) {
               ...
              } else if (annotation instanceof QueryName) {
               ...
              } else if (annotation instanceof QueryMap) {
                ...
              } else if (annotation instanceof Header) {
                ...
              } else if (annotation instanceof HeaderMap) {
                ...
              } else if (annotation instanceof Field) {
                ...
              } else if (annotation instanceof FieldMap) {
                ...
              } else if (annotation instanceof Part) {
                ...
              } else if (annotation instanceof PartMap) {
                ...
              }
              return null; // Not a Retrofit annotation.
            }
    }
    ...
}
  • ServiceMethod.parseAnnotations中最后是调用HttpServiceMethod.parseAnnotations获取ServiceMethod实例的
 static  HttpServiceMethod parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    ...
    //获取方法注解
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      ...
    } else {
      //网络请求方法的返回值类型就是请求适配器的类型
      adapterType = method.getGenericReturnType();
    }
    //请求适配器
    CallAdapter callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    ...
    //数据解析器
    Converter responseConverter =
        createResponseConverter(retrofit, method, responseType);
    //从retrofit获取请求工厂,默认的话是OkHttpClient
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    }
    ...
  }

  //CallAdapted继承了HttpServiceMethod
 static final class CallAdapted extends HttpServiceMethod {
    private final CallAdapter callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter responseConverter,
        CallAdapter callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    //adapt方法的实现,调用callAdapter的adapt方法
    @Override
    protected ReturnT adapt(Call call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }
  • 到这里我们就知道了Retrofit的create方法中的loadServiceMethod(method).invoke(args),实际是调用的HttpServiceMethod的invoke方法
  • 那么我们看一下HttpServiceMethod的invoke方法,其中调用的adapt方法就是上面CallAdapted的adapt,传入的call类型为OkHttpCall;
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
  • 从上面代码可以知道Retrofit中的Call实际是用的OkHttpCall
OkHttpCall 的同步请求方法 execute
  • 从上面Retrofit的create方法我们知道,下面代码中的call.execute实际是调用了OkHttpCall的execute方法
val apiService = retrofit.create(ApiService::class.java)
val call = apiService.searRepos(1, 5)
val response: Response = call.execute()
if (response.isSuccessful) {
    val repo = response.body()
    LjyLogUtil.d(repo.toString())
} else {
    LjyLogUtil.d(IOException("Unexpected code $response").message)
}
  • OkHttpCall.execute代码如下,其中创建的一个okHttp库的Call对象,到这就说明了Retrofit中的网络请求实际是交给okHttp处理的;
    @Override
    public Response execute() throws IOException {
        okhttp3.Call call;
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;
          //创建okhttp3.Call
          call = getRawCall();
        }

        if (canceled) {
          call.cancel();
        }

        return parseResponse(call.execute());
    }

    @GuardedBy("this")
    private okhttp3.Call getRawCall() throws IOException {
        okhttp3.Call call = rawCall;
        if (call != null) return call;
        ...
        return rawCall = createRawCall();
        ...
    }
    private okhttp3.Call createRawCall() throws IOException {
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
    }
  • 上面execute中通过getRawCall获取okhttp3.Call,getRawCall中又通过createRawCall中的callFactory.newCall创建okhttp3.Call,newCall的入参是通过requestFactory.create创建的请求对象
OkHttpCall 的异步请求方法 enqueue
  • 上面看过了同步请求的过程,异步请求也是一样通过okHttp.Call进行异步请求的
  @Override
  public void enqueue(final Callback callback) {
    Objects.requireNonNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          throwIfFatal(t);
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response response;
            try {
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }

            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }

          @Override
          public void onFailure(okhttp3.Call call, IOException e) {
            callFailure(e);
          }

          private void callFailure(Throwable e) {
            try {
              callback.onFailure(OkHttpCall.this, e);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
        });
  }
OkHttpCall 的 parseResponse方法
  • 通过上面代码我们发现OkHttpCall的同步异步请求都调用了parseResponse方法,其代码如下,
    其中通过 T body = responseConverter.convert(catchingBody),用数据解析器对响应体进行解析,
    这个responseConverter就是ServiceMethod的build方法调用createResponseConverter方法返回的Converter;
  Response parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse =
        rawResponse
            .newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

Retrofit中的设计模式

Builder(建造者)模式
  • 将复杂对象的构建和表示相分离,使复杂对象的构建简单化
  • 防止构造方法参数过多,造成使用者使用不便,通过链式调用不同方法设置不同参数
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()
  • 关于建造者模式如需了解更多内容可以查看Android设计模式-2-建造者模式
工厂模式
  • 将“类实例化的操作”与“使用对象的操作”分开,降低耦合,易于扩展,有利于产品的一致性
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .client(okHttpClient)
    // 自定义的Converter一定要放在官方提供的Converter前面
    .addConverterFactory(StringConverterFactory.create())
    .addConverterFactory(MapConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(LjyCallAdapterFactory.create())
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()
  • 关于工厂模式如需了解更多内容可以查看:
    • Android设计模式-4.1-简单工厂模式
    • Android设计模式-4.2-工厂方法模式
    • Android设计模式-5-抽象工厂模式
策略模式

— 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换。

  • 易于扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
val retrofit = Retrofit.Builder()
    .baseUrl(baseUrl)
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .addCallAdapterFactory(Java8CallAdapterFactory.create())
    .addCallAdapterFactory(GuavaCallAdapterFactory.create())
    .build()
  • 关于策略模式如需了解更多内容可以查看Android设计模式-6-策略模式
观察者模式
  • 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新
//call为被观察者,Callback为观察者
call.enqueue(object : Callback {
    override fun onResponse(call: Call, result: Response) {
        if (result.body() != null) {
            val repoResult: RepoList = result.body()!!
            for (it in repoResult.items) {
                LjyLogUtil.d("${it.name}_${it.starCount}")
            }
        }
    }

    override fun onFailure(call: Call, t: Throwable) {
        LjyLogUtil.d("onFailure:${t.message}")
    }

})
  • 关于观察者模式如需了解更多内容可以查看Android设计模式-11-观察者模式
适配器模式
  • 定义一个包装类,用于包装不兼容接口的对象
  • 可以让没有关联的类一起运行,提高了类的复用
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public @Nullable CallAdapter get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    ...
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    return new CallAdapter>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call adapt(Call call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }
}
 
  
  • 适配器模式在Android中最常见的使用就是listView,recycleView的Adapter
  • 关于适配器模式如需了解更多内容可以查看Android设计模式-19-适配器模式
装饰模式
  • 动态扩展一个实现类的功能,装饰类和被装饰类可以独立发展,不会相互耦合
//ExecutorCallbackCall是装饰者,而里面真正去执行网络请求的还是OkHttpCall
static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback callback) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback() {
            @Override
            public void onResponse(Call call, final Response response) {
              callbackExecutor.execute(
                  () -> {
                    if (delegate.isCanceled()) {
                      // Emulate OkHttp's behavior of throwing/delivering an IOException on
                      // cancellation.
                      callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                    } else {
                      callback.onResponse(ExecutorCallbackCall.this, response);
                    }
                  });
            }

            @Override
            public void onFailure(Call call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }
}
  • 关于装饰模式如需了解更多内容可以查看Android设计模式-20-装饰模式
外观模式
  • 为复杂的模块或子系统提供外界访问的接口
  • 通过创建一个统一的类,用来包装子系统中一个或多个复杂的类
  • Retrofit类就是Retrofit框架提供给我们的外观类
public final class Retrofit {
    private final Map> serviceMethodCache = new ConcurrentHashMap<>();

    final okhttp3.Call.Factory callFactory;
    final HttpUrl baseUrl;
    final List converterFactories;
    final List callAdapterFactories;
    final @Nullable Executor callbackExecutor;
    final boolean validateEagerly;
    ...
}
  • 关于外观模式如需了解更多内容可以查看Android设计模式-22-外观模式
代理模式
  • 也称委托模式,间接访问目标对象, 分为静态代理和动态代理
//Retrofit.create
public  T create(final Class service) {
    validateServiceInterface(service);
    return (T)
        //通过动态代理创建接口的实例
        Proxy.newProxyInstance(
            //参数1:classLoader
            service.getClassLoader(),
            //参数2:接口类型数组
            new Class[] {service},
            //参数3:实现了InvocationHandler的代理类
            new InvocationHandler() {
             ...
            });
}
  1. 静态代理
abstract class AbsObject {
    abstract fun doSomething()
}

class RealObject : AbsObject() {
    override fun doSomething() {
        LjyLogUtil.d("RealObject.doSomething")
    }
}

class ProxyObject(private val realObject: RealObject) : AbsObject() {
    override fun doSomething() {
        LjyLogUtil.d("before RealObject")
        realObject.doSomething()
        LjyLogUtil.d("after RealObject")
    }
}

//使用
val realObject = RealObject()
val proxyObject = ProxyObject(realObject)
proxyObject.doSomething()
  1. 动态代理
interface Subject {
    fun doSomething()
}

class Test : Subject {
    override fun doSomething() {
        LjyLogUtil.d("Test.doSomething")
    }
}

class DynamicProxy(private val target: Subject) : InvocationHandler {
    override fun invoke(proxy: Any?, method: Method?, args: Array?): Any? {
        LjyLogUtil.d("Proxy:${proxy?.javaClass?.name}")
        LjyLogUtil.d("before target")
        //Kotlin中数组转为可变长参数,通过前面加*符号
        val invoke = method!!.invoke(target, *(args ?: emptyArray()))
        LjyLogUtil.d("after target")
        return invoke
    }
}

//使用:
val test = Test()
val myProxy = DynamicProxy(test)
val subject: Subject =
    Proxy.newProxyInstance(
        test.javaClass.classLoader,
        test.javaClass.interfaces,
        myProxy
    ) as Subject
subject.doSomething()
LjyLogUtil.d("subject.className:" + subject.javaClass.name)
  • 关于代理模式如需了解更多内容可以查看Android设计模式-17-代理模式

参考文章

  • square/retrofit
  • Retrofit谷歌官方详解
  • 你真的会用Retrofit2吗?Retrofit2完全教程
  • Android网络编程(十一)源码解析Retrofit
  • Android:手把手带你 深入读懂 Retrofit 2.0 源码
  • Android主流三方库源码分析(二、深入理解Retrofit源码)

我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章

你可能感兴趣的:(Android进阶笔记,android,java,Retrofit)