Dagger Hilt单例场景下Retrofit拦截器读取SharedPreference始终返回旧值如何解决
问题根因
该问题与Hilt的单例注入逻辑无关,核心原因出在自定义SharedPrefs封装类的实现逻辑:
- 最常见的场景是
SharedPrefs在初始化时一次性读取token值缓存到成员变量,后续调用getToken()直接返回缓存值,没有实时读取系统SharedPreference存储的最新值 - 少数场景为存储token时使用的SharedPreference实例与
SharedPrefs内部依赖的实例参数不一致(比如文件名、访问模式不同)
修复方案
最优方案:修改SharedPrefs读取逻辑,每次调用实时取值
无需调整现有Hilt注入配置,直接修改SharedPrefs的getToken()方法,每次调用都从系统SharedPreference实例中读取最新值,不要将token缓存到成员变量中:
class SharedPrefs(private val context: Context) { // 仅全局持有系统SharedPreference实例即可,系统本身会保证内存缓存同步 private val sp = context.getSharedPreferences("自定义SP存储文件名", Context.MODE_PRIVATE) // 错误示例:初始化时仅读取一次缓存到成员变量,后续取值不会更新 // private val cachedToken = sp.getString("token", "") // fun getToken() = cachedToken ?: "" // 正确示例:每次调用都实时读取最新值 fun getToken(): String { return sp.getString("token", "") ?: "" } // 存储token时也使用同一个sp实例 fun saveToken(newToken: String) { sp.edit().putString("token", newToken).apply() } }
同时需要确保存储token时,使用Hilt注入的SharedPrefs实例调用saveToken方法,不要自行创建SharedPrefs实例或者直接操作SharedPreference文件存储,避免两边实例不一致。
优化建议
建议给SharedPrefModule的提供方法加上@Singleton注解,保证全局只有一个SharedPrefs包装类实例,避免不必要的对象创建开销:
@Module @InstallIn(SingletonComponent::class) object SharedPrefModule { @Singleton @Provides fun provideSharedPref(@ApplicationContext context: Context) : SharedPrefs{ return SharedPrefs(context) } }
内容的提问来源于stack exchange,提问作者Prieyudha Akadita S
相关产品推荐
相关产品推荐

