简体   繁体   中英

How to translate Retrofit client from Kotlin to Java preserving singleton?

I am trying to translate Java Retrofit Api client code to Kotlin. So here is what we have in Java:

Retrofit client which returns retrofit singleton object:

public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient(String baseUrl) {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

And Api client which uses the above retrofit object:

public class ApiUtils {

    public static final String BASE_URL = "https://api.stackexchange.com/2.2/";

    public static SOService getSOService() {
        return RetrofitClient.getClient(BASE_URL).create(SOService.class);
    }
}

The problem is that in every example I have seen so far on the internet, uses companion object(every member inside it is static), why then our singleton pattern passes away? Why not to use object instead of companion object and how to do that? See the example with companion object in Kotlin:

interface WikiApiService {

    @GET("api.php")
    fun hitCountCheck(@Query("action") action: String): Observable<Model.Result>

    companion object {
        fun create(): WikiApiService {

            val retrofit = Retrofit.Builder()
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("https://en.wikipedia.org/w/")
                    .build()

            return retrofit.create(WikiApiService::class.java)
        }
    }

Let alone that this is done in the same class, using companion object will result in returning new object of both retrofit and WikiApiService. I cannot be agree with it. Please make any clarifications about these examples. Maybe I don't get anything that's why this seems to me wrong and please forgive that I have put different examples for Java and Kotlin.

Don't try to return WikiApiService every time.

you can create a class

class RetData {

    private lateinit var retrofit: Retrofit

    var wikiApiService: WikiApiService

    init {
        if (!::retrofit.isInitialized) {
            retrofit = Retrofit.Builder()
                    .baseUrl("https://api.stackexchange.com/2.2/")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
        }
        wikiApiService = retrofit.create(WikiApiService::class.java)
    }
}

and access

fun test() {
    val retrofit = RetData()

    val apiService = retrofit.wikiApiService
    println(apiService)

    val apiService2 = retrofit.wikiApiService
    println(apiService2)

    val apiService3 = retrofit.wikiApiService
    println(apiService3)

    val apiService4 = retrofit.wikiApiService
    println(apiService4)
}

It's a better idea use dependency injection library like dagger 2

If you want make singleton in Kotlin, just... use object, not class.

object Retrofit {
    val instance = ...
}

see # https://kotlinlang.org/docs/reference/object-declarations.html for more example of object pattern in Kotlin.

But it's still bad practice. Is's much better to use DI framework, like Kodein or Dagger2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM