Android笔记(十九):JetPack DataStore 之 Preferences DataStore

Jetpack DataStore 是一种数据存储解决方案,主要适用于小型数据的处理。它可以通过协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。DataStore有两种实现方式(1)Preferences DataStore 和 (2)Proto DataStore.

Preferences DataStore利用键值对实现对简单数据的读写存储。这种方式不需要预定架构,也不确保类型安全。

一、增加依赖库

要使用Preferences DataStore需要在项目模块的build.gradle.kt中增加如下的依赖库:

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

        // 可选项-用于RxJava2支持
        implementation("androidx.datastore:datastore-preferences-rxjava2:1.0.0")

        // 可选项-用于 RxJava3 支持
        implementation("androidx.datastore:datastore-preferences-rxjava3:1.0.0")
} 

下面通过一个简单的实例来了解Perference DataStore的应用。在这个例子中, 记录当前账号访问的次数。运行效果如下图所示。
Android笔记(十九):JetPack DataStore 之 Preferences DataStore_第1张图片

二、定义一个实用类DatastoreUtils

利用该实用类DatastoreUtils实现对数据的读写操作。

class DataStoreUtils(val context:Context){
    //利用preferenceDataStore创建委托来创建Preferences DataStore实例
    private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name="settings")
    //定义关键字email
    private val EMAIL = stringPreferencesKey("email")
    //定义关键字counter
    private val COUNTER = intPreferencesKey("counter")
    //设置关键字对应存储的email值保存在Flow中
    val emailFlow: Flow<String> = context.dataStore.data.map {
        it[EMAIL]?:""
    }
    //设置关键字对应存储的counter值保存在Flow中
    val counterFlow:Flow<Int> = context.dataStore.data.map{
        it[COUNTER]?:0
    }

    /**
     * 定义挂起函数
     * 设置email账号对应访问应用的次数
     */
    suspend fun storeData(email:String){
        context.dataStore.edit{settings:MutablePreferences->
            val storedEmailValue = settings[EMAIL]?:""
            val storedCounterValue = settings[COUNTER]?:0

            if(storedEmailValue.isBlank()||storedEmailValue!=email) {
                settings[EMAIL] = email
                settings[COUNTER]= 1
            }else{
                settings[COUNTER] = storedCounterValue+1
            }
        }
    }
}

三 、定义界面MainScreen

在界面的组合函数MainScreen中调用DatastoreUtils实现对数据的读取操作。代码如下:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen(dataStoreUtils: DataStoreUtils,modifier:Modifier = Modifier){
    val context = LocalContext.current

    var emailInput by remember{mutableStateOf("[email protected]")}
    var rememberInput by remember{mutableStateOf(false)}
    var content by remember{mutableStateOf("")}

    val scope = rememberCoroutineScope()
    //读取数据
    LaunchedEffect(Unit){
            dataStoreUtils.counterFlow.collect{c:Int->
                dataStoreUtils.emailFlow.collect{account:String->
                    content = "账号:${account}访问次数是:${c}次"
                }
            }
    }
    Column{
        TextField(modifier = Modifier.fillMaxWidth(),
            value = emailInput,
            onValueChange = {it:String->
                emailInput = it
            },
            label ={Text("输入账号")},
            leadingIcon = {
                Icon(imageVector = Icons.Filled.Email,contentDescription = "账号")
            }
        )
        Row{
            Checkbox(checked = rememberInput, onCheckedChange ={
                 rememberInput = it
                 if(rememberInput)
                 scope.launch {
                     //写入数据
                     dataStoreUtils.storeData(emailInput)
                 }
            })
            Text("记住账号")
        }

        if(!emailInput.isBlank())
            Text(text = content ,fontSize=20.sp)

    }
}

说明:因为在应用中,活动界面中只能有一个Preferences DataStore的活动实例,因此在上述代码中对DataStore处理的DatastoreUtils实用类通过传参传递过来。也可以考虑使用单例模式,在整个应用中只有一个处理DataStore的对象实例。

四、定义主活动MainActivity

在主活动中调用主界面。代码如下:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ForCourseTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MainScreen(DataStoreUtils(this))
                }
            }
        }
    }
}

启动应用,可以在Device Explorer中的data->data目录下找到应用包,在它的下级目录files->datastore的settings.preferences_pb文件中保存键值对数据。如下图所示:
Android笔记(十九):JetPack DataStore 之 Preferences DataStore_第2张图片
图1 模拟器中存放的键值对数据

参考文献

DataStore
https://developer.android.google.cn/topic/libraries/architecture/datastore?hl=zh-cn

你可能感兴趣的:(android,笔记)