Skip to content

Latest commit

 

History

History
113 lines (92 loc) · 4.24 KB

36-Android-Retrofit2-自定义CallAdapter.md

File metadata and controls

113 lines (92 loc) · 4.24 KB
toc comments title description tags id categories date
false
true
Retrofit2-自定义 CallAdapter
Retrofit2-自定义 CallAdapter
Android
36
Android
2018-05-28

第一步

以下代码来自:https://github.com/googlesamples/android-architecture-components

这里要把 Call< JavaBean> 包装成 LiveData< ApiResponse< JavaBean>> ,除了 LiveData 外,Apisponse 和 JavaBean 都是自己写的

自定义 XXXCallAdapterFactoty 继承 Retrofit2.CallAdapter.Factory

/**
 * 日后这里基本上就是直接复制粘贴
 * 像 Call 改成 LiveData Response 换成 ApiResponse
 * 只需要把 LiveData::class.java 和 ApiResponse::class.java 换成自定义的类型
 * 如果只需要自定义 Call ,请将下面的 ApiResponse 换成默认 Response
 * getRaw():通过参数拿到包装该参数的类型
 */
class LiveDataCallAdapterFactory : Factory() {
    //重写get函数
    override fun get(
            returnType: Type,
            annotations: Array<Annotation>,
            retrofit: Retrofit
    ): CallAdapter<*, *>? {

        // 检查接口中函数的 Call 类型是否一致
        if (getRawType(returnType) != LiveData::class.java) return null

		// 检查 Call / LiveData
        if (observableType !is ParameterizedType) {
            throw IllegalArgumentException("resource must be parameterized")
        }

        // 获取默认 Response 类型 
        val observableType = getParameterUpperBound(0, returnType as ParameterizedType)

        // 获取 Response 位置的真实类型,这里是 ApiResponse
        val rawObservableType = getRawType(observableType)

        // 检查 Response / ApiResponse
        if (rawObservableType != ApiResponse::class.java) {
            throw IllegalArgumentException("type must be a resource")
        }

        // 通过 Call/ LiveData 来生成 body 类型
        val bodyType = Factory.getParameterUpperBound(0, observableType)

		// 返回自定义的 CallAdapter
        return LiveDataCallAdapter<Any>(bodyType)
    }
}

第二步

自定义 XXXCallAdapter 继承 Retrofit2.CallAdapter

  • 为了能接收到 Factory 传过来的 responseBody,别忘了给构造函数添加参数: val responseType: Type。
  • 为了能接收到 Factory 传过来的 泛型 any ,记得定义泛型参数。
  • 基类的 CallAdapter 需要传两个泛型参数: Factoty 传过来的 any; 第二个就是我们要包装成的类型 LiveData< ApiResponse< R>>
/**
 * 为了能接收到 Factory 传过来的 responseBody
 * 别忘了添加构造函数的参数 val responseType: Type
 */
class LiveDataCallAdapter<R>(private val responseType: Type) :
        CallAdapter<R, LiveData<ApiResponse<R>>> {

    //Factory 传过来的 body
    override fun responseType() = responseType

	//该函数返回的就是我们要包装成的类型,这里返回 LiveData< ApiResponse< R>> 
	//所以直接创建一个 LiveData< ApiResponse< R>> 对象并将其返回
	//期间可以利用 LiveData 对象来处理各种调用逻辑
	//熟悉的 Call 对象,可以直接对数据进行操作
    override fun adapt(call: Call<R>): LiveData<ApiResponse<R>> {
        return object : LiveData<ApiResponse<R>>() {
            private var started = AtomicBoolean(false)//借助原子类来保证线程安全
            override fun onActive() {
                super.onActive()
                if (started.compareAndSet(false, true)) {//确保里面代码不被多线程抢占
                    call.enqueue(object : Callback<R> {
                        override fun onResponse(call: Call<R>, response: Response<R>) {
                            postValue(ApiResponse.create(response))
                        }

                        override fun onFailure(call: Call<R>, throwable: Throwable) {
                            postValue(ApiResponse.create(throwable))
                        }
                    })
                }
            }
        }
    }
}

再推荐一个类:Retrofit2 + Kotlin 协程