摘要
使用MMKV数据框架实现设置页数据同步,设置页可以对其他页面进行设置;设置页数据通过MMKV框架持久化存储,重启APP不丢失.
关键信息
- Android Studio:Iguana | 2023.2.1
- Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zip
- jvmTarget = '1.8'
- minSdk 24
- targetSdk 34
- compileSdk 34
- 开发语言:Kotlin,Java
- ndkVersion = '21.1.6352462'
- kotlin版本:1.9.20
- kotlinCompilerExtensionVersion '1.5.4'
- com.android.library:8.3
原理简介
MMKV框架
[https://juejin.cn/post/7230649998870396983]
[https://github.com/tencent/mmkv]
MMKV作为一种高性能大量数据的存储组件,对比Android传统的存储方式SharedPreferences和SQLite确实有不少优势。核心是使用mmap内存映射文件,对比传统IO,在性能上有很大优势,并且将读写文件的操作变得和操作内存一样简单。
MMKV引入增量写入,重整内存,通过文件大小校验对多进程操作感知,多进程读写锁等等。但它的缺点是可能造成内存的浪费,因为必须映射内存页的整数倍,如果只存储很少量的数据,则显得大材小用。因此,可以作为一种数据存储的选择方案,在一些需要大量存储数据场景时,替代SharedPreferences。
通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操作系统负责将内存回写到文件,不必担心 crash 导致数据丢失。
安卓App的设置页开发
[https://juejin.cn/post/7130609032447918110]
[https://mbd.baidu.com/newspage/data/dtlandingsuper?nid=dt_5434129139457149730]
实现
核心代码
- 添加KKVM依赖
build.gradle
/* start 数据同步框架相关 */
implementation 'com.tencent:mmkv:1.3.4'
/* end 数据同步框架相关 */
- 新建BootApp类继承自Application类
BootApp.kt
package cn.qsbye.grape_yolov5_detect_android
import android.app.Application
import android.graphics.Bitmap
import android.util.Log
import com.tencent.mmkv.MMKV
import com.zynksoftware.documentscanner.ui.DocumentScanner
// 需要设置AndroidManifest.xml文件使用.BootApp启动以在应用初始化时自动调用
class BootApp:Application() {
companion object {
private const val FILE_SIZE = 1000000L
private const val FILE_QUALITY = 100
private val FILE_TYPE = Bitmap.CompressFormat.JPEG
}
override fun onCreate() {
super.onCreate()
/* start 初始化MMKV库 */
// 初始化,默认的保存地址是: /data/user/0/应用包名/files/mmkv
val rootDir = MMKV.initialize(this)
Log.d("MMKV","mmkv root:$rootDir")
/* end 初始化MMKV库 */
}
}
- 修改AndroidManifest.xml让BootApp类随应用启动;注册设置页.
AndroidManifest.xml
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/grape_icon_round"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true"
android:name=".BootApp"
android:theme="@style/Theme.Grapeyolov5detectandroid"
tools:targetApi="31">
<activity
android:name=".SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
</application>
- 设置页
Settings.kt
package cn.qsbye.grape_yolov5_detect_android
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import cn.qsbye.grape_yolov5_detect_android.ui.theme.Grapeyolov5detectandroidTheme
import com.tencent.mmkv.MMKV
class SettingsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Grapeyolov5detectandroidTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
SettingsPage()
}
}
}
}
}
@Composable
fun SettingsPage() {
// 定义用于存储开关状态的键
val mmkv = MMKV.mmkvWithID("settings")
// 用于记住开关状态的变量
val isGrapeQualityEnabled = remember { mutableStateOf(mmkv.getBoolean("grape_quality_enabled", true)) }
val isCpuInferenceEnabled = remember { mutableStateOf(mmkv.getBoolean("cpu_inference_enabled", true)) }
// 设置页内容
Column {
// 葡萄品质开关
SettingItem(
title = "显示葡萄品质",
isChecked = isGrapeQualityEnabled.value,
onCheckedChange = {
isGrapeQualityEnabled.value = it
mmkv.putBoolean("grape_quality_enabled", it)
}
)
// 仅使用CPU进行推理开关
SettingItem(
title = "仅使用CPU进行推理",
isChecked = isCpuInferenceEnabled.value,
onCheckedChange = {
isCpuInferenceEnabled.value = it
mmkv.putBoolean("cpu_inference_enabled", it)
}
)
}
}
@Composable
fun SettingItem(title: String, isChecked: Boolean, onCheckedChange: (Boolean) -> Unit) {
Row(modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = title)
Switch(checked = isChecked, onCheckedChange = onCheckedChange)
}
}
效果
设置页 |
---|