【问题标题】:How to translate Retrofit client from Kotlin to Java preserving singleton?如何将改造客户端从 Kotlin 转换为 Java 保留单例?
【发布时间】:2018-06-12 05:05:34
【问题描述】:

我正在尝试将 Java Retrofit Api 客户端代码转换为 Kotlin。这就是我们在 Java 中所拥有的:

返回改造单例对象的改造客户端:

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

以及使用上述改造对象的 Api 客户端:

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

问题是到目前为止我在互联网上看到的每个示例都使用伴生对象(其中的每个成员都是静态的),为什么我们的单例模式会消失?为什么不使用对象而不是伴随对象以及如何做到这一点? 请参阅 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)
        }
    }

更不用说这是在同一个类中完成的,使用伴生对象将导致返回改造和 WikiApiService 的新对象。我不能同意。请对这些示例进行任何澄清。也许我没有得到任何东西,这就是为什么在我看来这是错误的,请原谅我为 Java 和 Kotlin 提供了不同的示例。

【问题讨论】:

    标签: java android kotlin singleton retrofit2


    【解决方案1】:

    不要尝试每次都返回 WikiApiService。

    你可以创建一个类

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

    和访问

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

    最好使用像dagger 2这样的依赖注入库

    【讨论】:

      【解决方案2】:

      如果你想在 Kotlin 中创建单例,只需...使用对象,而不是类。

      object Retrofit {
          val instance = ...
      }
      

      有关 Kotlin 中对象模式的更多示例,请参阅 #https://kotlinlang.org/docs/reference/object-declarations.html

      但这仍然是不好的做法。使用 DI 框架要好得多,比如 Kodein 或 Dagger2。

      【讨论】:

      • 我听说 Kodein 是一个服务定位器,而不是一个依赖注入框架。
      • True :P 有一种,姑且称之为error,因为Kodein - KOtlin DEpendency INjection,不过你说得对,其实不是DI框架,而是dependency retrieval container(你可以在Kodein 的描述)
      猜你喜欢
      • 2019-05-09
      • 2021-07-03
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-05
      • 2019-12-02
      • 2021-08-03
      相关资源
      最近更新 更多