Kotlin使用关键字reified优化Retrofit2

 问题场景:

retrofit大家都很熟悉.创建使用大概如下.

(1) 定义接口请求类

interface RetrofitService {
    @GET("/posts")
    fun getPosts(): Deferred<Response<List<Post>>>
}

(2)创建接口实体类

object RetrofitFactory {
    const val BASE_URL = "https://jsonplaceholder.typicode.com"

    fun createRetrofitService(): RetrofitService = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .client(getClient())
        .build()
        .create(RetrofitService::class.java)

    private fun getClient(): OkHttpClient =
        OkHttpClient.Builder().addInterceptor(LoggerInterceptor()).build()
}

(3)调用

object NetRepository {

    private val service: RetrofitService by lazy {
        RetrofitFactory.createRetrofitService()
    }

    fun getDeferredPost() = service.getPosts()

}

现在我现在我的应用里面对接的网络接口只有一种类型就是RetrofitService,假设这个Service是专门处理商品类型的网络请求.如果

这时候需求变更,需要在添加用户登录,支付等接口功能该如何设计代码呢?

方案一

BASE_URL是没变么,直接在RetrofitService接口类写完剩下的接口不就完事儿了.

分析:

这样是可以.但是不满足java设计模式的单一职责你的接口有关于支付的,有关于的用户信息的,又有关于支付相关的.这样代码不清爽.好你说可以忍受反正自己挖的坑自己含着泪也得填.如果连域名都变了,该怎么办?

方案二

那我创建多个接口对象就好了

object RetrofitFactory {
    const val BASE_URL = "https://jsonplaceholder.typicode.com"

    const val BASE_URL1 = "https://jsonplaceholder.typicode.com1"

    fun createRetrofitService(url: String): RetrofitService =
        createRetrofit(BASE_URL).create(RetrofitService::class.java)


    fun createRetrofitService1(url: String): RetrofitService1 =
        createRetrofit(BASE_URL1).create(RetrofitService1::class.java)


    private fun createRetrofit(url: String): Retrofit = Retrofit.Builder()
        .baseUrl(url)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .client(getClient())
        .build()

    private fun getClient(): OkHttpClient =
        OkHttpClient.Builder().addInterceptor(LoggerInterceptor()).build()
}

分析:

确实解决了方案1的痛点,但是2个写起来看起来还不费事,试试看10个,20个..这样代码里面充满了大量类似的代码.我们是不是可以合并同类项目呢?

方案三

这边很有人就想起来泛型,但是在java里面有泛型擦除,但是到了kotlin我们就可以解决了这个问题.koltin里面有个保留关键子reified翻译成中文是具体化.它的作用就是这个是为了满足inline特性而设计的语法糖,因为给函数使用内联之后,编译器会用其函数体来替换掉函数调用,而如果该函数里面有泛型就可能会出现编译器不懂该泛型的问题,所以引入reified,使该泛型被智能替换成对应的类型.

object RetrofitFactory {
    const val BASE_URL = "https://jsonplaceholder.typicode.com"

    const val BASE_URL1 = "https://jsonplaceholder.typicode.com1"

    inline fun <reified T> createRetrofitService(url: String): T =
        createRetrofit(url).create(getRetrofitService<T>())


    fun createRetrofit(url: String): Retrofit = Retrofit.Builder()
        .baseUrl(url)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .client(getClient())
        .build()

    inline fun <reified T> getRetrofitService(): Class<T> = T::class.java


    private fun getClient(): OkHttpClient =
        OkHttpClient.Builder().addInterceptor(LoggerInterceptor()).build()
}

调用类

object NetRepository {

    private val service: RetrofitService by lazy {
        RetrofitFactory.createRetrofitService<RetrofitService>(RetrofitFactory.BASE_URL)
    }

    private val service1: RetrofitService1 by lazy {
        RetrofitFactory.createRetrofitService<RetrofitService1>(RetrofitFactory.BASE_URL1)
    }

    fun getPost() {
        service.getPosts()
    }

    fun getPost1() {
        service1.getPosts()
    }
}

分析:

通过泛型T直接获得具体类RetrofitService,RetrofitService1.这样以后增加接口,只要写接口类,域名url,其他代码都可以保持不变.减少了后期维护的工作量.代码请见https://github.com/ThinkJarvis/Mvvm/

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值