You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Hilt注入PreferenceFile到TokenAuthenticator时出现未初始化错误的求助

使用Hilt注入PreferenceFile到TokenAuthenticator时出现未初始化错误的求助

Hey there! Let's figure out why you're getting that "lateinit property preferenceFile has not been initialized" error. The main issues are with how you're handling injection in your TokenAuthenticator and a small mistake in your PreferenceFile setup. Here's how to fix it step by step:

1. Fix TokenAuthenticator to use Constructor Injection

Right now, you're using field injection (@Inject on the properties) in a class that already has an @Inject constructor(). For regular non-Android classes like TokenAuthenticator, Hilt relies on constructor injection to pass dependencies—field injection won't work here because Hilt doesn't automatically inject fields for these classes.

Update your TokenAuthenticator to take dependencies directly in the constructor:

class TokenAuthenticator @Inject constructor(
    private val retrofitApi: RetrofitApi,
    private val preferenceFile: PreferenceFile
) : Authenticator {

    override fun authenticate(route: Route?, response: Response): Request? {
        val refreshTokenIs = preferenceFile.retrieveKey(refreshToken)
        val responseRefresh = retrofitApi.refreshToken(refreshTokenIs ?: "")
        
        return if (responseRefresh.isSuccessful) {
            val newAccessToken = responseRefresh.body()
            
            preferenceFile.storeKey(token, newAccessToken?.token ?: "")
            preferenceFile.storeKey(refreshToken, newAccessToken?.refreshToken ?: "")
            preferenceFile.storeKey(tokenType, newAccessToken?.type ?: "")
            
            response.request.newBuilder()
                .header(AUTH_PARAM, "${newAccessToken?.type} ${newAccessToken?.token}")
                .build()
        } else {
            Log.e("sessionExpired", "===sessionExpired")
            MainActivity.context.get()?.sessionExpired()
            null
        }
    }
}

2. Fix PreferenceFile to Avoid Singleton Editor

Your current setup injects a singleton SharedPreferences.Editor, which is incorrect. Editors are meant to be created per edit operation—reusing a single editor instance can lead to unexpected behavior (like unsaved changes) after you call apply() or commit().

Update your PreferenceFile to create a new editor each time you need to modify preferences:

class PreferenceFile @Inject constructor(
    val sharedPreferences: SharedPreferences
) {

    fun storeKey(key: String, value: String) {
        sharedPreferences.edit()
            .putString(key, value)
            .apply()
    }

    fun storeBoolKey(key: String, value: Boolean) {
        sharedPreferences.edit()
            .putBoolean(key, value)
            .apply()
    }

    fun retrieveKey(key: String): String? {
        return sharedPreferences.getString(key, null)
    }

    fun retrieveBoolKey(key: String): Boolean {
        return sharedPreferences.getBoolean(key, false)
    }

    fun <T> storeObject(key: String, data: T) {
        val jsonString = GsonBuilder().create().toJson(data)
        sharedPreferences.edit()
            .putString(key, jsonString)
            .apply()
    }

    inline fun <reified T> getStoreObject(key: String): T? {
        val json = sharedPreferences.getString(key, null)
        return GsonBuilder().create().fromJson(json, T::class.java)
    }

    fun clearPreference() {
        sharedPreferences.edit()
            .clear()
            .apply()
    }
}

3. Simplify Your PrefModule

Since we no longer inject the SharedPreferences.Editor, you can remove that provider from your module. Keep only the SharedPreferences provider:

@InstallIn(SingletonComponent::class)
@Module
class PrefModule {

    @Provides
    @Singleton
    fun getPref(@ApplicationContext context: Context): SharedPreferences =
        context.getSharedPreferences(preferenceName, Context.MODE_PRIVATE)
}

4. Quick Checks to Ensure Everything Works

  • Make sure your RetrofitApi is properly provided in a Hilt module (e.g., via Retrofit.create(RetrofitApi::class.java)).
  • Verify that your OkHttpClient is created using Hilt, with the TokenAuthenticator injected into it:
    @Provides
    @Singleton
    fun provideOkHttpClient(tokenAuthenticator: TokenAuthenticator): OkHttpClient {
        return OkHttpClient.Builder()
            .authenticator(tokenAuthenticator)
            // Add other configs like interceptors or timeouts here
            .build()
    }
    
  • Ensure your app class is annotated with @HiltAndroidApp (required for Hilt to initialize):
    @HiltAndroidApp
    class MyApp : Application() { }
    

These changes should resolve the lateinit error because Hilt will now properly inject PreferenceFile and RetrofitApi into TokenAuthenticator via its constructor, and your preference operations will use the correct editor instances.

备注:内容来源于stack exchange,提问作者Suraj Bahadur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 06:14:38