iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Mobile Development

Jetpack Compose 從心開始系列 第 21

Jetpack Compose 從心開始 Day21 - 使用 DataStore 儲存

  • 分享至 

  • xImage
  •  

前言

   SQL 和 Room 儲存功能太強大了,可以用簡單一點嗎?
   有的那就是用 DataStore

什麼是 DataStore?

DataStore 是 Android Jetpack 提供的一種新的資料儲存解決方案,用於替換 SharedPreferences。它提供了一個更安全、更現代的方式來儲存鍵值對資料,並與 Kotlin Coroutines 緊密整合。

為何選擇 DataStore?

  • 型別安全: DataStore 允許您定義資料的型別,避免了 SharedPreferences 中容易發生的型別轉換錯誤。
  • 非同步操作: DataStore 使用協程,確保資料存取操作在背景執行,不會阻塞主線程。
  • 流式 API: DataStore 提供了流式 API,可以方便地觀察資料的變化。
  • 更好的性能: DataStore 在某些情況下比 SharedPreferences 具有更好的性能。

如何使用 DataStore

在app/build.gradle.kts 檔案的 dependencies 中:

implementation("androidx.datastore:datastore-preferences:1.0.0")

實作使用者偏好設定存放區

新建立 UserPreferencesRepository 的新類別

class UserPreferencesRepository(
    private val dataStore: DataStore<Preferences>
){
    val isLinearLayout: Flow<Boolean> = dataStore.data
        .catch {
            if(it is IOException) {
                Log.e(TAG, "Error reading preferences.", it)
                emit(emptyPreferences())
            } else {
                throw it
            }
        }
        .map { preferences ->
            preferences[IS_LINEAR_LAYOUT] ?: true
        }

    suspend fun saveLayoutPreference(isLinearLayout: Boolean) {
        dataStore.edit { preferences ->
            preferences[IS_LINEAR_LAYOUT] = isLinearLayout
        }
    }
    private companion object {
        val IS_LINEAR_LAYOUT = booleanPreferencesKey("is_linear_layout")
    }
}

初始化 DataStore

新建立 DessertReleaseApplication 的新類別

class DessertReleaseApplication: Application() {
    lateinit var userPreferencesRepository: UserPreferencesRepository

    override fun onCreate() {
        super.onCreate()
        userPreferencesRepository = UserPreferencesRepository(dataStore)
    }
}

使用 UserPreferencesRepository

在 DessertReleaseViewModel 中使用 UserPreferencesRepository

class DessertReleaseViewModel(
    private val userPreferencesRepository: UserPreferencesRepository
) : ViewModel() {
    private val _uiState = MutableStateFlow(DessertReleaseUiState())

    // UI states access for various [DessertReleaseUiState]
    val uiState: StateFlow<DessertReleaseUiState> =
        userPreferencesRepository.isLinearLayout.map { isLinearLayout ->
            DessertReleaseUiState(isLinearLayout)
        }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5_000),
                initialValue = DessertReleaseUiState()
            )


    /*
     * [selectLayout] change the layout and icons accordingly and
     * save the selection in DataStore through [userPreferencesRepository]
     */
    fun selectLayout(isLinearLayout: Boolean) {
        viewModelScope.launch {
            userPreferencesRepository.saveLayoutPreference(isLinearLayout)
        }
    }

    companion object {
        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = (this[APPLICATION_KEY] as DessertReleaseApplication)
                DessertReleaseViewModel(application.userPreferencesRepository)
            }
        }
    }
}

執行結果

https://ithelp.ithome.com.tw/upload/images/20241001/20121643P2hNlEhz6K.png

https://ithelp.ithome.com.tw/upload/images/20241001/20121643vUfD4jMD6A.png

參考

https://developer.android.com/codelabs/basic-android-kotlin-compose-navigation?hl=zh-tw


上一篇
Jetpack Compose 從心開始 Day20 - 使用 Room
下一篇
Jetpack Compose 從心開始 Day22 - 使用 WorkManager 安排工作
系列文
Jetpack Compose 從心開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言