DataStore快速上手1-preference

news/2024/7/23 23:22:10 标签: kotlin, android, 开发语言

DataStore 概念

DataStore 可以存储两种类型的数据,一种是 preference,一种是 protobuf

每个进程在同一时间内仅能打开一个 DataStore 实例(或者通过其他管理手段来实现多个 DataStore 交替使用)

一个 DataStore 可以视为一张数据表


默认存储位置:data/data/com.xxx.xxx/files/datastore/xxx.pb


快速上手

导入依赖:implementation "androidx.datastore:datastore-preferences:1.0.0"


目标

将三个属性 name、age、habit 按照键值对的方式使用 preference 模式存储到本地

实现查询功能


datastore 主文件

新建文件 DataStoreInit.kt 用来初始化 DataStore

首先需要确定 DataStore 的名字,或者可以理解为这个数据表的名字

并使用 kotlin 特有的扩展方法的语法,直接把 dataStore 绑定在全局上下文,即可“一次初始化全局使用”

kotlin">// 定义DataStore名字
private const val BASIC_DB_NAME = "basic_test"

// 全局委托实例化DataStore,接收一个参数,即名字
private val Context.dataStore by preferencesDataStore(name = BASIC_DB_NAME)

我们需要在外部定义键的类型

xxxPreferencesKey 其中的 xxx 代表类型

kotlin">// 直接定义一组类型时最好这样写
private object PreferencesKeys{
    // 变量名(大写字符)为开发时使用的键名
    // 括号内的名字为存储到本地的键名
    val BASIC_NAME = stringPreferencesKey("basic_name")
    val BASIC_AGE =  stringPreferencesKey("basic_age")
    val BASIC_HABIT = stringPreferencesKey("basic_habit")
}

直接定义一个数据类,方便我们后续直接提取出三个数据!

kotlin">data class basicModel(val name:String,val age:String,val habit:String)

编写新类 DataStoreInit,他接受一个 context 上下文作为初始化形参

所有的 CRUD 操作都在此类中进行!

kotlin">class DataStoreInit(private val context: Context) {
    ...
}

读取数据

读取数据时需要使用 trycatch 代码块进行异常捕获

kotlin">// 下面代码是固定格式,不要纠结
val getBasicDB = context.dataStore.data
.catch {e->
    // 捕获异常并作出处理
    if(e is IOException){
        emit(emptyPreferences())
    }else{
        throw e
    }
}.map {preferences ->
    // 依据键值对的方式提取出存储的值
    // 格式:preferences[定义的键名]
    // ?:类似于三元运算,即左侧取出null则直接使用右侧值替换之
    val name = preferences[PreferencesKeys.BASIC_NAME] ?: "无名氏"
    val age = preferences[PreferencesKeys.BASIC_AGE] ?: "inf"
    val habit = preferences[PreferencesKeys.BASIC_HABIT] ?: "清心寡欲乜有爱好"

    // 把所有数据存储到数据类并将它返回!
    basicModel(name, age, habit)
}

写入数据

数据写入需要使用挂起函数(故调用该方法时也要使用协程作用域)

kotlin">// 挂起函数,接收三个参数作为值输入
suspend fun insertBasicDB(name: String,age: String,habit: String):String{
    return try {
        // 依据键值对存储即可
        context.dataStore.edit {preferences ->
            preferences[PreferencesKeys.BASIC_NAME] = name
            preferences[PreferencesKeys.BASIC_AGE] = age
            preferences[PreferencesKeys.BASIC_HABIT] = habit
        }
        "基础数据插入成功"
    }catch (e:Exception){
        println(e)
        "基础数据插入失败"
    }
}

主 UI

主页面配置:三个输入框,加一个插入按钮、一个查询按钮、一个清空表单按钮

功能大体解释:

  1. 判断输入框有任意一个为空,则不允许插入
  2. 根据返回值判断成功与否并弹出 Toast
  3. 使用协程作用域 rememberCoroutineScope 进行读写操作
kotlin">@Composable
fun DataStoreViewInit(navHostController: NavHostController){
    // 三个主要变量,记得remember
    var name by remember {
        mutableStateOf("tom")
    }
    var age by remember {
        mutableStateOf("100")
    }
    var habit by remember {
        mutableStateOf("play")
    }

    // 定义协程作用域,用于数据读写
    val scope = rememberCoroutineScope()

    Column(
        Modifier
            .fillMaxHeight()
            .fillMaxWidth(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        TextField(value = name, onValueChange = {name=it}, label = { Text(text = "用户名")})
        TextField(value = age, onValueChange = {age=it}, label = { Text(text = "年龄")})
        TextField(value = habit, onValueChange = {habit=it}, label = { Text(text = "密码")})

        // 保存数据按钮
        Button(onClick = {
            // 判断编辑框均非空
            if(name!==""&&age!==""&&habit!==""){
                scope.launch {
                    // 保存数据
                    val res = DataStoreInit(MainContext).insertBasicDB(name, age, habit)
                    DialogUtil(MainContext).showSimpleToast(res)
                }
            }else{
                DialogUtil(MainContext).showSimpleToast("请填完所有信息!!!")
            }
        }) {
            Text(text = "提交信息")
        }

        // 查询数据按钮
        Button(onClick = {
            try {
                scope.launch {
                    // 查询数据
                    // 由于挂起函数返回类型为一个flow类型对象,所以使用collect取出值即可
                    DataStoreInit(MainContext).getBasicDB.collect {
                        name = it.name
                        age = it.age
                        habit = it.habit
                    }
                }
                DialogUtil(MainContext).showSimpleToast("已经取出数据!")
            }catch (e:Exception){
                DialogUtil(MainContext).showSimpleToast("完蛋了找不到数据!")
            }
        }) {
            Text(text = "查询信息")
        }

        // 清空表单按钮
        Button(onClick = {
            name=""
            age=""
            habit=""
        }) {
            Text(text = "清空表单")
        }
    }
}

补上一个我封装的弹出 Toast 的小工具类

kotlin">class DialogUtil(private val context: Context) {
    fun showSimpleToast(str:String){
        Toast.makeText(context,str,Toast.LENGTH_SHORT).show()
    }
}


http://www.niftyadmin.cn/n/52676.html

相关文章

蓝牙单点技术实现路径介绍

本文主要介绍蓝牙设备与手机一对一相连的 蓝牙单点 技术。 准备工作 系统要求&#xff1a;蓝牙使用需要安卓 4.3 以及以上版本&#xff0c;智能生活 App SDK 从安卓 4.4 开始支持。Manifest 权限&#xff1a; <uses-permission android:name"android.permission.ACCE…

Python:每日一题之全球变暖(DFS连通性判断)

题目描述 你有一张某海域 NxN 像素的照片&#xff0c;"."表示海洋、"#"表示陆地&#xff0c;如下所示&#xff1a; ....... .##.... .##.... ....##. ..####. ...###. ....... 其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿…

大数据技术架构(组件)28——Spark:Memory Model(1)

2.1.8、Memory Model2.1.8.1、Tungsten Origin background众所周知&#xff0c;Spark是由ScalaJava开发的一种基于内存计算的大数据解决方案&#xff0c;底层运行在JVM上&#xff0c;那么自然而然的会有GC的问题反过来限制Spark的性能&#xff0c;而且绝大多数Spark应用程序的主…

如何使用逻辑分析仪,解析通信数据

如何使用逻辑分析仪&#xff0c;解析通信数据使用工具&#xff1a;逻辑分析仪&#xff08;几十块买的裸板&#xff09;&#xff0c;软件是&#xff1a;PulseView一、在开发或者移植某一个模块时&#xff0c;你可能遇到这样的问题&#xff1a;二、逻辑分析仪的使用使用工具&…

【GPLT 二阶题目集】L2-012 关于堆的判断

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种&#xff1a; x is the root&#xff1a;x是根结点&#xff1b; x and y are siblings&#xff1a;x和y是兄弟结点&#xff1b; x is the parent of y&#xff1a;x是y的父结…

LeetCode栈与队列相关解法

栈与队列1. 用栈实现队列[232. 用栈实现队列](https://leetcode.cn/problems/implement-queue-using-stacks/)2. 用队列实现栈[225. 用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/)两个队列实现一个队列实现3. 有效括号[20. 有效的括号](https://…

深圳活动会议媒体邀约,电视台,网媒媒体资源

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;一&#xff0c;您可以考虑以下几种方式邀请媒体参加深圳的活动会议&#xff1a;1&#xff0c;直接联系&#xff1a;找到相关媒体的联系人信息&#xff0c;发送邀请函或电话邀请。2&#xff0c;通过公关公司&…

同向双指针题目练习

3.无重复字符的最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 经典题目&#xff0c;不再赘述&#xff0c;思路直接看代码 class Solution {public int lengthOfLongestSubstring(String s) {int max 0, left 0, right 0;boolean…