Issue
I am struggling to translate this retrofit class into Kotlin. It is basically a singleton that works as a client and I am not sure of my Kotlin implementation. UserAPI and ProfileAPI are just interfaces.
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;
}
}
And this is my Kotlin implementation. As I understand this, the init block will be executed first when the class is instantiated.
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)
}
}
But something tells me this is not the right way or it can be done better. Is there anything I can improve here?
UPDATE!!!
Based on comments and answer I have this implementation now
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)
}
}
Then I would use it like this
RetrofitService.profileApi
Would that be alright?
Solution
You could use something like:
object MyApi {
private const val BASE_URL = " https://www.MYAPI.com/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = 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
is a singleton it'll only instance it once and reuse for next callby lazy
using this keyword, yourretrofitService
will only be initialised the first time you call and then you'll reuse that same value, for more details look here
Answered By - Biscuit
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)