上一篇講了如何宣告與如何高效管理與使用,這一篇要把他套用在setting上
先將舊有的SettingPage更換一下,讓他依照List來顯示
data class SettingsInfo<T>(
val title: String,
val description: String = "",
val appPreference: AppPreference<T>
)
val settingInfoList = listOf(
SettingsInfo<Boolean>("完成的排最後", "", AppPreference.FINISHED_DESC),
SettingsInfo<Int>("Nothing", "", AppPreference.NOTHING_INT)
)
現在也有泛型的List,需要針對不同種數據把它給展示出來
@Composable
fun <T>SettingItem(settingsInfo: SettingsInfo<T>) {
val value by SettingManager
.getValueFlow(settingsInfo.appPreference)
.collectAsState(initial = settingsInfo.appPreference.defaultValue)
val onChange: (T) -> Unit = { value ->
CoroutineScope(Dispatchers.IO).launch {
SettingManager.setValue(settingsInfo.appPreference, value)
}
}
when (value) {
is Boolean -> {
val pref = settingsInfo.appPreference as AppPreference<Boolean>
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier.fillMaxWidth(0.85f)
) {
Text(settingsInfo.title)
Switch(
checked = value as Boolean,
onCheckedChange = { onChange(it as T) }
)
}
}
is Int -> {
val pref = settingsInfo.appPreference as AppPreference<Int>
Column(
modifier = Modifier.fillMaxWidth(0.85f)
) {
Text("${settingsInfo.title}: $value/100")
Slider(
value = (value as Int).toFloat(),
onValueChange = { onChange(it.toInt() as T) },
valueRange = 0f..100f
)
}
}
else -> {
Text("${settingsInfo.title}: 未支援的型別")
}
}
}
//Setting Page
items(settingInfoList) {
SettingItem(it)
}
我大概講解一下我的作法:
<T>
宣告的,沒辦法在onCreate後,或是在App裡面,將datastore賦予給SettingManager,並呼叫init函數初始化
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 這兩行
SettingManager.dataStore = this.dataStore
SettingManager.init()
//
enableEdgeToEdge()
setContent {
Tutorial2025Theme {
App(
modifier = Modifier.padding()
)
}
}
}
因為有時候可能一不小心沒寫好導致錯誤的型別進入datastore裡面,他就會壞掉,這時候可以用init將初始值全部重設
也可以自己試試看自動偵測錯誤數值並重新賦值與log錯誤資訊
這樣子就可以順暢的使用Preferences DataStore了
這些是我前陣子讀然想到(找到)的方式,真的比hard coded好很多