在 Kotlin 中改造单例

Retrofit singleton in Kotlin

我正在努力将此改造 class 翻译成 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 实现。据我了解,初始化块将在实例化 class 时首先执行。

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

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

更新!!!

根据评论和回答,我现在有了这个实现

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

可以吗?

你可以使用类似的东西:

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 只会在您第一次调用时初始化,然后您将重复使用相同的值,了解更多详情
//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)
}
}