美文网首页
Android 架构组件 之 Data Store(9) - P

Android 架构组件 之 Data Store(9) - P

作者: 行走中的3卡 | 来源:发表于2022-11-13 19:33 被阅读0次

1. 定义将要在 proto 中保存的数据

user_prefs.proto 增加以下代码:

syntax = "proto3";

option java_package = "com.codelab.android.datastore";
option java_multiple_files = true;

message UserPreferences {
  // filter for showing / hiding completed tasks
  bool show_completed = 1;

  // defines tasks sorting order: no order, by deadline, by priority, by deadline and priority
  enum SortOrder {
    UNSPECIFIED = 0;
    NONE = 1;
    BY_DEADLINE = 2;
    BY_PRIORITY = 3;
    BY_DEADLINE_AND_PRIORITY = 4;
  }

  // user selected tasks sorting order
  SortOrder sort_order = 2;
}

其中,
枚举的默认值为枚举类型定义中列出的第一个值。但是从 SharedPreferences 向外迁移时,我们需要知道得到的值是默认值还是先前在 SharedPreferences 中设置的值。为此,我们为 SortOrder 枚举定义一个新值:UNSPECIFIED,并将其置于首位,这样它就可以作为默认值来使用。

清理并重构项目,确保生成一个包含新字段的新 UserPreferences 对象。

1.2 修改TasksViewModel.filterSortTasks()

由于我们还添加了 UNSPECIFIED 选项,接下来需要为 when(sortOrder) 语句添加另一个 case

private fun filterSortTasks(
    tasks: List<Task>,
    showCompleted: Boolean,
    sortOrder: SortOrder
): List<Task> {
    // filter the tasks
    val filteredTasks = if (showCompleted) {
        tasks
    } else {
        tasks.filter { !it.completed }
    }
    // sort the tasks
    return when (sortOrder) {
        SortOrder.UNSPECIFIED -> filteredTasks
        SortOrder.NONE -> filteredTasks
        SortOrder.BY_DEADLINE -> filteredTasks.sortedByDescending { it.deadline }
        SortOrder.BY_PRIORITY -> filteredTasks.sortedBy { it.priority }
        SortOrder.BY_DEADLINE_AND_PRIORITY -> filteredTasks.sortedWith(
            compareByDescending<Task> { it.deadline }.thenBy { it.priority }
        )
        // We shouldn't get any other values
        else -> throw UnsupportedOperationException("$sortOrder not supported")
    }
}

2. 从 SharedPreferences 向外迁移

private val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(
    fileName = DATA_STORE_FILE_NAME,
    serializer = UserPreferencesSerializer,
    produceMigrations = { context ->
        listOf(
            SharedPreferencesMigration(
                context,
                USER_PREFERENCES_NAME
            ) { sharedPrefs: SharedPreferencesView, currentData: UserPreferences ->
                // Define the mapping from SharedPreferences to UserPreferences
                if (currentData.sortOrder == SortOrder.UNSPECIFIED) {
                    currentData.toBuilder().setSortOrder(
                        SortOrder.valueOf(
                            sharedPrefs.getString(SORT_ORDER_KEY, SortOrder.NONE.name)!!
                        )
                    ).build()
                } else {
                    currentData
                }
            }
        )
    }
)

请更新 DataStore 构建器,并为 migrations 参数分配一个包含 SharedPreferencesMigration 实例的新列表:

private val dataStore: DataStore<UserPreferences> = context.createDataStore(
    fileName = "user_prefs.pb",
    serializer = UserPreferencesSerializer,
    migrations = listOf(sharedPrefsMigration)
)

3. 将排序顺序保存到 DataStore

suspend fun enableSortByDeadline(enable: Boolean) {
    // updateData handles data transactionally, ensuring that if the sort is updated at the same
    // time from another thread, we won't have conflicts
    dataStore.updateData { preferences ->
        val currentOrder = preferences.sortOrder
        val newSortOrder =
            if (enable) {
                if (currentOrder == SortOrder.BY_PRIORITY) {
                    SortOrder.BY_DEADLINE_AND_PRIORITY
                } else {
                    SortOrder.BY_DEADLINE
                }
            } else {
                if (currentOrder == SortOrder.BY_DEADLINE_AND_PRIORITY) {
                    SortOrder.BY_PRIORITY
                } else {
                    SortOrder.NONE
                }
            }
        preferences.toBuilder().setSortOrder(newSortOrder).build()
    }
}

现在,可以移除 context 构造函数参数和使用的所有 SharedPreferences。

--End --

相关文章

网友评论

      本文标题:Android 架构组件 之 Data Store(9) - P

      本文链接:https://www.haomeiwen.com/subject/hbtatdtx.html