如何在 Hilt (Android) 中重新初始化单例?

问题描述 投票:0回答:1

我的 Android 项目中有 Hilt DI 框架。我还有改造和 ApiNetworkModule 用于获取单例改造对象:

@Module
@InstallIn(SingletonComponent.class)
public class ApiNetworkModule {
...
    @Singleton
    @Provides
    public Retrofit provideRetrofit(
            OkHttpClient okHttpClient,
            Gson gson,
            SharedPrefManager sharedPrefManager
    ) {
        return new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(sharedPrefManager.getUrl())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
...
}

一般来说它工作得很好,但我注意到在

sharedPrefManager
中更新url时,改造对象不知道它并使用旧的url。只有在关闭-打开应用程序后才会完全更新。有没有办法以编程方式重新初始化
Retrofit
单例?或者如何正确处理?

android singleton retrofit retrofit2 dagger-hilt
1个回答
-1
投票

接收修改后的 URL 的 Retrofit 对象的方法是去掉 @Singleton 。如果删除@Singleton,则可以通过将修改后的URL应用于sharedPreferences来创建Retrofit对象,因为Retrofit对象是在创建存储库时创建并注入的。

@Module
@InstallIn(SingletonComponent.class)
public class ApiNetworkModule {
...
  
    @Provides
    public Retrofit provideRetrofit(
            OkHttpClient okHttpClient,
            Gson gson,
            SharedPrefManager sharedPrefManager
    ) {
        return new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(sharedPrefManager.getUrl())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
...
}

我们推荐这种方法,因为你想要的是一种在 URL 修改时创建并注入新对象的方法,而不是只存在于单例组件依赖树中的 Retrofit 对象。

--------------------更新---------------------------------------- -------------

使用SingletonComponent.class时,无法初始化,因为其生命周期与Application相同。首先,正如我所说,如果你删除@Singleton,你可以转换,但是重新创建有问题,所以我将告诉你如何使用Interceptor更改Api Url地址。

class HostSelectionInterceptor: Interceptor {
private val baseHost = TestApp.getPreference().getRestUrl().toHttpUrl().host

override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()

    if (TestApp.getPreference().isTestMode()) {
        val convertUrl = when (request.url.host) {
            baseHost -> {
                APIClient.BASE_TEST_REST_URL
            }
            else -> baseHost
        }

        val newUrl = request.url.newBuilder().host(convertUrl.toHttpUrl().host).build()
        val newRequest = request.newBuilder().url(newUrl).build()
        return chain.proceed(newRequest)
    }

    return chain.proceed(request)
    }
}

网络.类

private val okHttpClient: OkHttpClient by lazy {
    OkHttpClient.Builder()
        .addInterceptor(logInterceptor)
        .addInterceptor(HostSelectionInterceptor())
        .connectTimeout(TIMEOUT_CONNECT, TimeUnit.SECONDS)
        .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
        .writeTimeout(TIMEOUT_WRITE, TimeUnit.SECONDS)
        .build()
}

拦截器可以拦截服务器请求和响应并执行所需的操作。上面的示例是在测试模式下请求将 Base Url 更改为 Test Url 的示例。

我希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.