【问题标题】:Retrofit singleton in Kotlin在 Kotlin 中改造单例
【发布时间】:2020-08-26 23:58:57
【问题描述】:

我正在努力将这个改造类翻译成 Kotlin。它基本上是一个作为客户端工作的单例,我不确定我的 Kotlin 实现。 UserAPI 和 ProfileAPI 只是接口。

public class RetrofitService {

private static final String BASE_URL = "https://test.api.com/";
private ProfileAPI profileAPI;
private UserAPI userAPI;
private static RetrofitService INSTANCE;

/**
 * Method that returns the instance
 * @return
 */
public static RetrofitService getInstance() {
    if (INSTANCE == null) {
        INSTANCE = new RetrofitService();
    }
    return INSTANCE;
}

private RetrofitService() {
    Retrofit mRetrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .baseUrl(BASE_URL)
            .build();
    profileAPI = mRetrofit.create(ProfileAPI.class);
    UserAPI = mRetrofit.create(UserAPI.class);
}

/**
 * Method that returns the API
 * @return
 */
public ProfileAPI getProfileApi() {
    return profileAPI;
}

/**
 * Method that returns the API
 * @return
 */
public UserAPI getUserApi() {
    return userAPI;
}

}

这是我的 Kotlin 实现。据我了解,在实例化类时,将首先执行 init 块。

class RetrofitService private constructor() {
/**
 * Method that returns the API
 * @return
 */
private val profileApi: ProfileAPI
private val userAPI: UserAPI

companion object {
    private const val BASE_URL = "https://test.api.com/"
    private var INSTANCE: RetrofitService? = null

    /**
     * Method that returns the instance
     * @return
     */
    fun getInstance(): RetrofitService? {
        if (INSTANCE == null) {
            INSTANCE = RetrofitService()
        }
        return INSTANCE
    }
}

init {
    val mRetrofit = Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .baseUrl(BASE_URL)
            .build()
    profileApi = mRetrofit.create(ProfileAPI::class.java)
    UserAPI = mRetrofit.create(UserAPI::class.java)
}
}

但是有些事情告诉我这不是正确的方法,或者可以做得更好。这里有什么可以改进的吗?

更新!!!

基于 cmets 和回答我现在有了这个实现

object RetrofitService {
private const val BASE_URL = "https://test.api.com"

private fun retrofitService(): Retrofit {
    return Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .baseUrl(BASE_URL)
            .build()
}

val profileApi: ProfileAPI by lazy {
    retrofitService().create(ProfileAPI::class.java)
}

val userApi: UserAPI by lazy {
    retrofitService().create(UserAPI::class.java)
}
}

那我就这样用了

RetrofitService.profileApi

这样可以吗?

【问题讨论】:

  • RetrofitService 可以完全是一个对象。那么就不需要私有构造函数和init块了。

标签: java android kotlin singleton retrofit2


【解决方案1】:
//try to adapt this code sample to your code

object RetrofitConfig {
// use lazy to insure that only one instance of retrofit will be used - no duplication
private val retrofit : Retrofit by lazy {
    Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl("put_your_url_here")
        .build()
}

// here put your services interface if you have more
val movieService : MovieService by lazy {
    retrofit.create(MovieService::class.java)
}

val showService : ShowService by lazy {
    retrofit.create(ShowService::class.java)
}
}

【讨论】:

    【解决方案2】:

    你可以使用类似的东西:

    object MyApi {
    
        private const val BASE_URL = " https://www.MYAPI.com/"
    
        private val moshi = Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()
    
        private fun retrofit(): Retrofit {
            return Retrofit.Builder()
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .client(clientBuilder.build())
                .baseUrl(BASE_URL)
                .build()
        }
    
        val retrofitService: MyApiService by lazy {
            retrofit().create(MyApiService::class.java)
        }
    
        //If you want more service just add more val such as
        val otherService: MyOtherService by lazy {
            retrofit().create(MyOtherService::class.java
        }
    
    }
    
    //To use it you just need to do:
    MyApi.retrofitService
    MyApi.otherService
    
    
    • object ClassName 是一个 singleton 它只会实例化一次并重用于下一次调用
    • by lazy 使用这个关键字,你的 retrofitService 只会在你第一次调用时被初始化,然后你会重复使用相同的值,更多细节 look here

    【讨论】:

    • 谢谢@Biscuit。我用你的建议更新了我的问题。现在好看了吗?
    • 是的,你的更新完全没问题,我也可以这样做,我已经在我的回答中添加了它
    • 不是每个服务都有新的改造实例吗?我们在每次服务初始化时调用 retrofit()
    • 是的,确实,将为每个服务创建一个新实例,因此对于我的示例,只会创建 2 个改造对象,您可以将函数 retrofit() 更改为 val retrofit: Retrofit by lazy 来解决此问题
    猜你喜欢
    • 2018-08-31
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 2023-03-27
    • 2014-10-28
    • 1970-01-01
    相关资源
    最近更新 更多