尝试将共享首选项实现为单例,以将用户首选项存储在我的应用程序中。我已经在应用程序的各个地方实现了匕首和刀柄,但我对它的理解仍然很不稳定。
这是我的键值存储类
class KeyValueStore @Inject constructor(
private val sharedPreferences: SharedPreferences
) {
fun getString(key: SharedPreferenceKey) = sharedPreferences.getString(key.name, "")
fun getBoolean(key: SharedPreferenceKey) = sharedPreferences.getBoolean((key.name), false)
fun setString(vararg values: Pair <SharedPreferenceKey, String>) = sharedPreferences.edit{
values.forEach { (key, value) ->
putString(key.name, value)
}
}
fun setBoolean(vararg values: Pair <SharedPreferenceKey, Boolean>) = sharedPreferences.edit{
values.forEach { (key, value) ->
putBoolean(key.name, value)
}
}
fun clearValue(key: SharedPreferenceKey) = sharedPreferences.edit{
remove(key.name)
}
fun clear() = sharedPreferences.edit{
clear()
}
}
然后在我的 appModule 中我尝试初始化单例
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun sharedPreferences(@ApplicationContext context: Context): SharedPreferences{
return sharedPreferences(context)
}
}
这里还初始化了其他存储库,也用于我的数据访问(通过对象框),并且已经工作了一段时间,但我只是复制了与共享首选项相关的内容。
我尝试在我的主要活动中使用键值存储
@ExperimentalAnimationApi
@ExperimentalPagerApi
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject lateinit var splashViewModel: SplashViewModel
@Inject lateinit var keyValueStore: KeyValueStore
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun onCreate(savedInstanceState: Bundle?) {
var keepSplashOnScreen = true
val delay = 1000L
installSplashScreen().setKeepOnScreenCondition { keepSplashOnScreen }
Handler(Looper.getMainLooper()).postDelayed({ keepSplashOnScreen = false }, delay)
super.onCreate(savedInstanceState)
initialiseApp()
setContent {
FL_DatatrackerTheme {
val screen by splashViewModel.startDestination
SetupNavGraph(startDestination = screen)
}
}
}
private fun initialiseApp(){
if(!keyValueStore.getBoolean(SettingsKeys.ONBOARDING_COMPLETE)){
keyValueStore.setBoolean(Pair(SettingsKeys.ONBOARDING_COMPLETE, false))
keyValueStore.setString(Pair(SettingsKeys.CURRENT_PRESET, "Default"))
}
}
}
并尝试在视图模型的 SplashScreen 中使用 keyValueStore。此类处理我在第一个屏幕之前显示的入门部分。
class SplashViewModel @Inject constructor(
private val keyValueStore: KeyValueStore
) : ViewModel() {
private val _isLoading: MutableState<Boolean> = mutableStateOf(true)
private val _startDestination: MutableState<String> = mutableStateOf(Screen.Welcome.route)
val startDestination: State<String> = _startDestination
init {
viewModelScope.launch {
if (keyValueStore.getBoolean(SettingsKeys.ONBOARDING_COMPLETE)) {
_startDestination.value = Screen.HomeScreen.route
} else {
_startDestination.value = Screen.Welcome.route
}
}
_isLoading.value = false
}
}
一切看起来都不错并且可以构建,但随后我收到堆栈溢出错误
E FATAL EXCEPTION: main
Process: com.jorotayo.fl_datatracker, PID: 5186 java.lang.StackOverflowError: stack size 8188KB
at com.jorotayo.fl_datatracker.dependencyInjection.AppModule.sharedPreferences(Unknown Source:2)
at com.jorotayo.fl_datatracker.dependencyInjection.AppModule.sharedPreferences(AppModule.kt:131)
任何帮助将不胜感激
尝试过各种类型的共享首选项初始化,甚至尝试以不同的方式在应用程序上下文中检索。这是我得到的最远的结果,因为该应用程序实际上已构建。其他东西甚至无法构建