【问题标题】:Reinitialize singleton class after app restart应用重启后重新初始化单例类
【发布时间】:2020-07-20 23:04:51
【问题描述】:

应用程序使用单例。其中一个包含Retrofit 客户端的实例。另一个包含常量。

我可以在应用偏好设置中更改服务器 URL(在活动中),以便在应用重启后我希望使用新的基本 URL 重新初始化 Retrofit 客户端。

在第一次启动后,所有的单例和类都被初始化。然后我更改活动中的 URL 并重新启动应用程序。现在单例不会初始化并包含旧常量。如果我强制停止应用程序或附加调试器,这些单例将按预期重新启动。

object ApiClass {

    private val gsonConverter: GsonConverter = GsonConverter()
    var gson: Gson
        private set
    var retrofit: Retrofit
        private set

    init {
        Timber.i("*** start ApiClass")

        val okHttpClient = OkHttpClient().newBuilder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .build()

        gson = GsonBuilder().setLenient().create()

        val url = "..." // Get a server URL from preferences.
        Timber.i("*** " + url)

        retrofit = Retrofit.Builder()
            .baseUrl(url)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
        ...
    }
}

/////////////

object ApiConst {

    init {
        Timber.i("*** start ApiConst")
    }

    const val SOME_TEXT = "text"
}

如何在没有Force stop 应用的情况下重新初始化单例?

【问题讨论】:

  • 我怀疑 Android 可能会保留您的应用程序的某些状态,事实是有状态的全局变量通常是有问题的,简单的解决方案是添加一个调用来重新初始化您的“ApiClass”。更好的解决方案是停止使用单例并将对象与应用程序生命周期联系起来
  • @al3c,谢谢!也许将ApiClass 更改为stackoverflow.com/questions/41672427/… 会有所帮助(著名的getInstance())。我会测试。

标签: android kotlin initialization singleton


【解决方案1】:

感谢@al3c,我发现重新初始化单例是没有用的。我试图将一种形式的单例更改为另一种形式(如How to make a singleton for retrofit 2?):

class ApiClass {

    var gson: Gson private set
    lateinit var retrofit: Retrofit private set
    private val gsonConverter: GsonConverter = GsonConverter()
    private val okHttpClient: OkHttpClient

    init {
        Timber.i("*** start ApiClass")

        okHttpClient = OkHttpClient().newBuilder()
        ...
   }

    companion object {
        private var instance: ApiClass? = null

        fun getInstance(): ApiClass {
            if (instance == null) instance = ApiClass()
            return instance!!
        }
    }
}

但是调用ApiClass.getInstance().retrofit 并没有帮助我在重启后重新创建ApiClass。然后我尝试在销毁应用程序之前更改Retrofit 客户端中的基本 URL(这样重启后它将有一个新 URL)。看完Retrofit - Change BaseUrl我写道:

fun setBaseUrl(url: String) {
    retrofit = Retrofit.Builder()
        .baseUrl(url)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
}

然后我可以从onDestroy 的首选项活动中调用setBaseUrl 来更改Retrofit 客户端。此外,它还帮助我继续使用具有新请求 URL 的应用程序,因此我不必重新启动应用程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 2015-10-01
    • 1970-01-01
    相关资源
    最近更新 更多