iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

上一篇講了如何宣告與如何高效管理與使用,這一篇要把他套用在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)  
}

我大概講解一下我的作法:

  • 建立通用的部分:數據Flow與更改
  • 用when偵測value型別來選擇,如果不小心cast錯了型別,他也會自動歸類到else裡面
  • 不同的部分我要讓編譯器知道我的pref是確切的型別,因為我已經有確認過了,所以直接cast
  • 因為value還是T型別,所以在顯示的時候要先cast
  • 同上,儘管我知道了型別,但是onChange就是用<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好很多


上一篇
Day 24:紀錄零碎信息,使用DataStore
系列文
現代Android jetpack compose開發入門25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言