MMKV(2)
-
API
-
初始化和实例获取:
-
MMKV.initialize(Context context): 初始化MMKV库。通常在应用程序的入口点调用此方法。
-
MMKV.defaultMMKV(): 获取默认的MMKV实例。默认实例使用默认的存储路径和加密方式。
-
MMKV.mmkvWithID(String mmapID): 根据给定的ID获取MMKV实例。可以使用不同的ID创建多个MMKV实例,每个实例都有独立的数据存储。
-
-
存储数据:
-
putBoolean(String key, boolean value): 存储布尔类型的数据。
-
putInt(String key, int value): 存储整数类型的数据。
-
putLong(String key, long value): 存储长整数类型的数据。
-
putFloat(String key, float value): 存储浮点数类型的数据。
-
putDouble(String key, double value): 存储双精度浮点数类型的数据。
-
putString(String key, String value): 存储字符串类型的数据。
-
putBytes(String key, byte[] value): 存储字节数组类型的数据。
-
putParcelable(String key, Parcelable value): 存储实现了Parcelable接口的自定义对象数据。
-
-
读取数据:
-
getBoolean(String key, boolean defaultValue): 读取布尔类型的数据。
-
getInt(String key, int defaultValue): 读取整数类型的数据。
-
getLong(String key, long defaultValue): 读取长整数类型的数据。
-
getFloat(String key, float defaultValue): 读取浮点数类型的数据。
-
getDouble(String key, double defaultValue): 读取双精度浮点数类型的数据。
-
getString(String key, String defaultValue): 读取字符串类型的数据。
-
getBytes(String key): 读取字节数组类型的数据。
-
getParcelable(String key, Class<T> clazz): 读取实现了Parcelable接口的自定义对象数据。
-
-
删除数据:
-
remove(String key): 删除指定键的数据。
-
removeValues(String[] keys): 删除指定键数组的数据。
-
-
清除数据:
-
clear(): 清除所有数据。
-
-
其他操作:
-
contains(String key): 检查是否包含指定键的数据。
-
getAllKeys(): 获取所有键的数组。
-
synchronize(): 同步数据到磁盘。
-
-
高级功能:
-
encode(String key, Object value): 存储任意类型的数据,包括自定义对象。
-
decodeXXX(String key): 读取任意类型的数据,包括自定义对象。
-
setLogLevel(int level): 设置日志级别。
-
setCryptKey(byte[] key): 设置数据加密密钥。
-
import com.tencent.mmkv.MMKV;public class MMKVExample {public static void main(String[] args) {// 初始化MMKV库MMKV.initialize("/path/to/directory");// 获取默认的MMKV实例MMKV mmkv = MMKV.defaultMMKV();// 存储数据mmkv.putString("name", "John Doe");mmkv.putInt("age", 25);mmkv.putBoolean("isStudent", true);// 读取数据String name = mmkv.decodeString("name");int age = mmkv.decodeInt("age");boolean isStudent = mmkv.decodeBool("isStudent");// 输出读取的数据System.out.println("Name: " + name);System.out.println("Age: " + age);System.out.println("Is Student: " + isStudent);// 删除数据mmkv.remove("age");// 检查数据是否存在boolean containsName = mmkv.containsKey("name");boolean containsAge = mmkv.containsKey("age");System.out.println("Contains name: " + containsName);System.out.println("Contains age: " + containsAge);// 清除所有数据mmkv.clear();}
}
import com.tencent.mmkv.MMKV;public class MMKVExample {public static void main(String[] args) {// 初始化MMKV库MMKV.initialize("/path/to/directory");// 获取默认的MMKV实例MMKV mmkv = MMKV.defaultMMKV();// 检查是否包含指定键的数据boolean containsKey = mmkv.containsKey("name");System.out.println("Contains key: " + containsKey);// 获取所有键的数组String[] allKeys = mmkv.getAllKeys();System.out.println("All keys: ");for (String key : allKeys) {System.out.println(key);}// 同步数据到磁盘mmkv.synchronize();// 存储任意类型的数据,包括自定义对象CustomObject customObject = new CustomObject("John", 25);mmkv.encode("customObject", customObject);// 读取任意类型的数据,包括自定义对象CustomObject decodedObject = mmkv.decodeParcelable("customObject", CustomObject.class);System.out.println("Decoded object: " + decodedObject);// 设置日志级别MMKV.setLogLevel(MMKV.LogLevel.LevelInfo);// 设置数据加密密钥byte[] key = "encryptionKey".getBytes();mmkv.setCryptKey(key);}
// 自定义对象示例static class CustomObject {private String name;private int age;public CustomObject(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "CustomObject{" +"name='" + name + '\'' +", age=" + age +'}';}}
}
存储和读取原理(上文有提及)
-
存储原理:
-
MMKV使用mmap(内存映射文件)技术将数据存储在文件中。在初始化MMKV时,它会创建一个特定的文件,并将其映射到进程的地址空间中的一个字节数组。
-
写入数据时,MMKV会将数据直接写入内存中的字节数组,而不是频繁地写入磁盘文件。这样可以避免磁盘IO的开销,提高了写入性能。
-
MMKV使用了Copy-on-Write(写时复制)技术,即在写入数据时,会先将要修改的数据复制到新的内存区域,然后进行修改。这样可以避免对原始数据的破坏,同时减少了数据复制的开销。
-
-
读取原理:
-
读取数据时,MMKV会直接从内存中的字节数组中读取数据,而不需要进行磁盘读取操作。这样可以极大地提高读取速度,尤其在频繁读取大量数据的场景下效果显著。
-
为了快速定位和读取指定键的数据,MMKV使用了索引结构。索引结构可以是哈希表、跳表或B+树等,它们都具有快速查找的特性,可以高效地从内存中的字节数组中定位和获取对应键的数据。
-
共享数据
两个进程中共享一个计数器
在A进程:
// 初始化 MMKV 实例
MMKV.initialize(context);
MMKV mmkv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);// 写入初始值
int counterValue = 0;
mmkv.encode("counter", counterValue);// 递增计数器
counterValue = mmkv.decodeInt("counter", 0);
counterValue++;
mmkv.encode("counter", counterValue);
在B进程:
// 初始化 MMKV 实例
MMKV.initialize(context);
MMKV mmkv = MMKV.mmkvWithID("shared_data", MMKV.MULTI_PROCESS_MODE);// 读取计数器值
int counterValue = mmkv.decodeInt("counter", 0);
System.out.println("Counter value in Process B: " + counterValue);
进程 A 和进程 B 都使用相同的进程名 "shared_data" 来初始化 MMKV 实例,并将 MULTI_PROCESS_MODE 模式用于进程共享数据。
在进程 A 中,初始时将计数器的值设置为 0,并将其存储在 MMKV 中。然后,递增计数器的值,并将更新后的值再次存储在 MMKV 中。
在进程 B 中,通过相同的进程名初始化 MMKV 实例,并从 MMKV 中读取计数器的值。由于进程 A 和进程 B 共享相同的 MMKV 实例,进程 B 将能够读取到进程 A 更新后的计数器值。
序列反序列
MMKV 本身并不提供直接的对象序列化功能,但可以使用其他库(如 Gson、Jackson 等)将对象转换为字符串或字节数组进行存储和读取。
下面是一个示例,展示了如何使用 Gson 库将对象序列化为 JSON 字符串,并存储到 MMKV 中,然后再从 MMKV 中读取并反序列化为对象。
// 定义一个自定义对象
public class Person {private String name;private int age;// 省略构造函数、getter 和 setter 方法@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}// 序列化对象并存储到 MMKV
Person person = new Person("John", 25);
Gson gson = new Gson();
String json = gson.toJson(person);
mmkv.encode("person", json);// 从 MMKV 中读取并反序列化对象
String savedJson = mmkv.decodeString("person", null);
Person savedPerson = gson.fromJson(savedJson, Person.class);System.out.println("Saved Person: " + savedPerson);
在上述示例中,定义了一个名为 Person 的自定义对象,并使用 Gson 库将其转换为 JSON 字符串。然后使用 mmkv.encode("person", json) 将 JSON 字符串存储到 MMKV 中。
在读取时,使用 mmkv.decodeString("person", null) 从 MMKV 中获取存储的 JSON 字符串。然后使用 Gson 的 fromJson() 方法将 JSON 字符串反序列化为 Person 对象。
相关文章:
MMKV(2)
API 初始化和实例获取: MMKV.initialize(Context context): 初始化MMKV库。通常在应用程序的入口点调用此方法。 MMKV.defaultMMKV(): 获取默认的MMKV实例。默认实例使用默认的存储路径和加密方式。 MMKV.mmkvWithID(String mmapID): 根据给定的ID获取MMKV实例。…...
Spring Boot项目中使用 TrueLicense 生成和验证License(附源码)
1、Linux 在客户linux上新建layman目录,导入license.sh文件, [rootlocalhost layman]# mkdir -p /laymanlicense.sh文件内容: #!/bin/bash # 1.获取要监控的本地服务器IP地址 IPifconfig | grep inet | grep -vE inet6|127.0.0.1 | awk {p…...
ES6 Iterator 和 for...of 循环
1.iterator 概念 ES6 添加了Map和Set。这样就有了四种数据集合,需要一种统一的接口机制来处理所有不同的数据结构。遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部…...
ubuntu20.04 nvidia显卡驱动掉了,变成开源驱动,在软件与更新里选择专有驱动,下载出错,调整ubuntu镜像源之后成功修复
驱动配置好,环境隔了一段时间,打开Ubuntu发现装好的驱动又掉了,软件与更新 那里,附加驱动,显示开源驱动,命令行输入 nvidia-smi 命令查找不到驱动。 点击上面的 nvidia-driver-470(专有&#x…...
华为FAT模式无线AP配置实例
硬件:AP3010DN 软件版本:VRP software, Version 5.170 (AP3010DN-V2 FAT V200R010C00SPCf02) [Huawei]dis ver Huawei Versatile Routing Platform Software VRP (R) software, Version 5.170 (AP3010DN-V2 FAT V200R010C00SPCf02) Copyright (C) 2011…...
nodejs基于vue 学生论坛设计与实现
随着网络技术的不断成熟,带动了学生论坛,它彻底改变了过去传统的管理方式,不仅使服务管理难度变低了,还提升了管理的灵活性。 是本系统的开发平台 系统中管理员主要是为了安全有效地存储和管理各类信息, 这种个性化的平…...
017 基于Spring Boot的食堂管理系统
部分代码地址: https://github.com/XinChennn/xc017-stglxt 基于Spring Boot的食堂管理系统 项目介绍 本项目是基于Java的管理系统。采用前后端分离开发。前端基于bootstrap框架实现,后端使用Java语言开发,技术栈包括但不限于SpringBoot、…...
常用的二十种设计模式(下)-C++
设计模式 C中常用的设计模式有很多,设计模式是解决常见问题的经过验证的最佳实践。以下是一些常用的设计模式: 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。工厂模式(…...
C#桶排序算法
前言 桶排序是一种线性时间复杂度的排序算法,它将待排序的数据分到有限数量的桶中,每个桶再进行单独排序,最后将所有桶中的数据按顺序依次取出,即可得到排序结果。 实现原理 首先根据待排序数据,确定需要的桶的数量。…...
快速了解服务器单CPU与双CPU
在当今快节奏的技术环境中,用户们对功能强大且高效的服务器配置需求不断增长。CPU作为构成任何计算基础设施的骨干,服务器的“大脑”,负责执行计算、控制数据流并协调各个组件之间的任务,是服务器选择硬件中的重要一环。因此…...
c# Dictionary、ConcurrentDictionary的使用
Dictionary Dictionary 用于存储键-值对的集合。如果需要高效地存储键-值对并快速查找,请使用 Dictionary。 注意,键必须是唯一的,值可以重复。 using System; using System.Collections.Generic; using System.Linq;class Program {stati…...
大数据中间件——Kafka
Kafka安装配置 首先我们把kafka的安装包上传到虚拟机中: 解压到对应的目录并修改对应的文件名: 首先我们来到kafka的config目录,我们第一个要修改的文件就是server.properties文件,修改内容如下: # Licensed to the …...
HarmonyOS/OpenHarmony原生应用-ArkTS万能卡片组件Slider
滑动条组件,通常用于快速调节设置值,如音量调节、亮度调节等应用场景。该组件从API Version 7开始支持。无子组件 一、接口 Slider(options?: {value?: number, min?: number, max?: number, step?: number, style?: SliderStyle, direction?: Ax…...
SpringCloud: sentinel链路限流
一、配置文件要增加 spring.cloud.sentinel.webContextUnify: false二、在要限流的业务方法上使用SentinelResource注解 package cn.edu.tju.service;import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockExcept…...
UML 中的关系
种类 继承、实现、组合、聚合、关联、依赖 理解 继承和实现的关系强度最大。组合代表着实体之间共同构成一个主体内部的组成部分无法单独支撑,聚合则代表层级更高的一种关联涉及的实体都是独立的个体共同组合起来构成一个主体 个体之间是可以单独工作的。 组合和…...
ChatGPT技术或加剧钓鱼邮件攻击
我们对ChatGPT这一新技术并不陌生,也早就听闻ChatGPT可以通过某种方式绕过安全机制,对目标进行入侵。 ChatGPT的“越狱”技术已经迭代数次,甚至有了先进的“邪恶GPT”WormGPT和FraudGPT,两者都能快速实现钓鱼邮件骗局。 安全分析…...
哨兵1号后向散射系数土壤水分反演
哨兵1号后向散射系数土壤水分反演 数据导入 打开之前预处理之后的VH和VV极化的后向散射系数转存的tiff文件 导入实测点 选择KML转图层 kml文件是由奥维地图导出的.ovkml格式改后缀名得到的 提取采样点的后向散射系数 选择多值提取至点 右键打开点图层的属性表,发现…...
day3:Node.js 基础知识
day3:Node.js 基础知识 文章目录 day3:Node.js 基础知识创建第一个应用事件循环机制异步编程模块系统函数与回调函数路由和全局对象创建第一个应用 实例如下,在你项目的根目录下创建一个叫 helloworld.js 的文件,并写入以下代码: var http = require(http);http.cre…...
【RDMA】librdmacm库和连接建立过程
翻译:rdma_cm - RDMA通信管理器。 概述:rdma_cm是用于建立RDMA传输上的通信的管理器。 说明:RDMA CM是一个用于建立可靠连接和不可靠数据报数据传输的通信管理器。它为建立连接提供了一个RDMA传输中立的接口。该API基于套接字,但…...
如何使用Python抓取PDF文件并自动下载到本地
目录 一、导入必要的库 二、发送HTTP请求并获取PDF文件内容 三、将PDF文件内容写入到本地文件中 四、完整代码示例 五、注意事项 六、错误处理和异常处理 七、进一步优化 总结 在Python中,抓取PDF文件并自动下载到本地需要使用几个不同的库。首先࿰…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
