Android性能优化:微信自用高性能持久化框架——MMKV组件原理_mmkv size(1)

本文介绍了MMKV库在Android应用中的使用,包括初始化、数据迁移、接口实现、性能比较、注意事项及限制,强调其在多进程环境下的优势和内存管理策略。

在 App 启动时初始化 MMKV,设定 MMKV 的根目录
(默认/data/data/xxx.xxx/files/mmkv/)
(sp存储在/data/data/xxx.xxx/shared_prefs/)

支持从SP迁移数据importFromSharedPreferences

MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface

// 可以跟SP用法一样
SharedPreferences.Editor editor = mmkv.edit();
// 无需调用 commit()
//editor.commit();


MMKV 的使用非常简单,所有变更立马生效,无需调用 sync、apply。 在 App 启动时初始化 MMKV,设定 MMKV 的根目录(files/mmkv/),例如在 MainActivity 里:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    String rootDir = MMKV.initialize(this);
    System.out.println("mmkv root: " + rootDir);
    //……
}


MMKV 提供一个全局的实例,可以直接使用:

import com.tencent.mmkv.MMKV;
//……

MMKV kv = MMKV.defaultMMKV();

kv.encode("bool", true);
boolean bValue = kv.decodeBool("bool");

kv.encode("int", Integer.MIN_VALUE);
int iValue = kv.decodeInt("int");

kv.encode("string", "Hello from mmkv");
String str = kv.decodeString("string");


使用完毕的几个方法

    public native void clearAll();

    // MMKV's size won't reduce after deleting key-values
    // call this method after lots of deleting f you care about disk usage
    // note that `clearAll` has the similar effect of `trim`
    public native void trim();

    // call this method if the instance is no longer needed in the near future
    // any subsequent call to the instance is undefined behavior
    public native void close();

    // call on memory warning
    // any subsequent call to the instance will load all key-values from file again
    public native void clearMemoryCache();

    // you don't need to call this, really, I mean it
    // unless you care about out of battery
    public void sync() {
        sync(true);
    }


性能对比

我们将 MMKV 和 SharedPreferences、SQLite 进行对比, 重复读写操作 1k 次。相关测试代码在 Android/MMKV/mmkvdemo/。结果如下图表。

单进程性能

可见,MMKV 在写入性能上远远超越 SharedPreferences & SQLite,在读取性能上也有相近或超越的表现。

多进程性能

可见,MMKV 无论是在写入性能还是在读取性能,都远远超越 MultiProcessSharedPreferences & SQLite & SQLite,
MMKV 在 Android 多进程 key-value 存储组件上是不二之选。

补充适用建议

如果使用请务必做code19版本的适配,这个在github官网有说明

依赖下面这个库,然后对19区分处理
implementation ‘com.getkeepsafe.relinker:relinker:1.3.1’

if (android.os.Build.VERSION.SDK_INT == 19) {
    MMKV.initialize(relativePath, new MMKV.LibLoader() {
        @Override
        public void loadLibrary(String libName) {
            ReLinker.loadLibrary(context, libName);
        }
    });
} else {
    MMKV.initialize(context);
}


限制

可看到,一个键会存入多分实例,最后存入的就是最新的。
MMKV 在大部分情况下都性能强劲,key/value 的数量和长度都没有限制。
然而 MMKV 在内存里缓存了所有的 key-value,在总大小比较大的情况下(例如 100M+),App 可能会爆内存,触发重整回写时,写入速度也会变慢。
支持大文件的 MMKV 正在开发中,有望在下一个大版本发布。

问题

数据变化监听 怎么获取?

// content change notification of other process
// trigger by getXXX() or setXXX() or checkContentChangedByOuterProcess()


多进程 issue
//CallStaticVoidMethod 错误写成 CallStaticIntMethod,方法匹配crash

registerOnSharedPreferenceChangeListener not support
//官方推荐使用event方式通知更新
Data-change-listener is not supported by design.
We suggest using something like event-bus to notify any interesting clients.
Doing this inside a storage framework smells really bad.

defaultMMKV 是单进程SINGLE_PROCESS_MODE
使用MULTI_PROCESS_MODE创建多进程

带来的APK尺寸增加问题

libc++_shared.so 252.5k

libmmkv.so 43.5k

implementation ‘com.tencent:mmkv:1.0.23’

// implementation ‘com.tencent:mmkv-static:1.0.23’ (无libc++_shared.so)

只打包需要的平台对应.so

    ndk {
            abiFilters "armeabi-v7a", 'x86'
        }


.so加载问题

implementation ‘com.getkeepsafe.relinker:relinker:1.3.1’

log太多

初始化可以设置log打印层级 initialize(rootDir, MMKVLogLevel.LevelInfo);
设置log转发,控制log输出格式、文件 MMKVHandler wantLogRedirecting=true

多进程

锁 lock unlock tryLock

注意如果一个进程lock住,另一个进程mmkvWithID获取MMKV时就阻塞住,直到持有进程释放。

        // get the lock immediately
        MMKV mmkv2 = MMKV.mmkvWithID(LOCK_PHASE_2, MMKV.MULTI_PROCESS_MODE);
        mmkv2.lock();
        Log.d("locked in child", LOCK_PHASE_2);

        Runnable waiter = new Runnable() {
            @Override
            public void run() {
                //阻塞住 直到其他进程释放
                MMKV mmkv1 = MMKV.mmkvWithID(LOCK_PHASE_1, MMKV.MULTI_PROCESS_MODE);
                mmkv1.lock();
                Log.d("locked in child", LOCK_PHASE_1);
            }
        };


注意:如果其他进程有进行修改,不会立即触发onContentChangedByOuterProcess,
checkLoadData如果变化,会clearMemoryState,重新loadFromFile。//数据量大时不要太频繁
读取decodeXXX会阻塞住,先回调onContentChangedByOuterProcess,再返回值,保证值是最新的。

总结

【Android 详细知识点思维脑图(技能树)】

我个人是做Android开发,已经有十来年了,目前在某创业公司任职CTO兼系统架构师。虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

最后,赠与大家一句话,共勉!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

份系统化的技术体系对大家有一个方向参考。

最后,赠与大家一句话,共勉!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值