在HarmonyOS NEXT 6.1.0(API 23)中,Preview Kit为2in1设备(二合一平板/PC)带来了通用文件缓存加速C API。这项能力旨在解决文件浏览场景中的三大痛点:硬件解码的二次等待、复杂对象的序列化难题以及设备兼容性编译问题。本文将手把手带你实现一套基于NDK的高保真双轨Fallback缓存引擎,包含初始化、普通字节缓存以及复杂对象自定义序列化存取。
一、核心API简介
缓存底座初始化需调用HMS_FileCacheBoost_Init,传入相对沙箱路径、缓存容量上限(单位MB)及数据库文件名。示例:- FileCacheBoost_ErrCode HMS_FileCacheBoost_Init(
- const char* path,
- size_t pathLen,
- uint32_t cacheUpperLimitMb,
- const char* dbName,
- size_t dbNameLen
- );
复制代码 对于纯字节数据(如解码后的像素裸流),使用AddObjectByKey和GetObjectByKey。每个缓存项需指定唯一Key(建议文件哈希)和权重Weight(高权重项优先保留)。注意调用Get后必须调用HMS_FileCacheBoost_FreeObject释放系统分配的内存。- FileCacheBoost_ErrCode HMS_FileCacheBoost_AddObjectByKey(
- const uint8_t *key, size_t keyLen,
- const uint8_t *data, size_t dataLen,
- uint32_t weight
- );
- FileCacheBoost_ErrCode HMS_FileCacheBoost_GetObjectByKey(
- const uint8_t *key, size_t keyLen,
- uint8_t **data, size_t *dataLen
- );
复制代码 针对包含成员指针的复杂C结构体(如图像对象),使用AddSerialObjectByKey和GetSerialObjectByKey。开发者需实现SerializeFunc和DeserializeFunc回调,通过WriteFunc/ReadFunc接口手动读写各成员字段,实现安全序列化。- typedef FileCacheBoost_CbErrCode (*SerializeFunc)(
- const void *object, WriteFunc writeFunc, struct CacheKey *key);
- typedef FileCacheBoost_CbErrCode (*DeserializeFunc)(
- void **object, ReadFunc readFunc, struct CacheKey *key);
复制代码
二、物理设备编译适配与双轨Fallback机制
libfile_cache_boost.so只存在于2in1设备的Native SDK中。在手机或模拟器上直接编译会报ld链接错误;运行时也会因缺少.so而闪退。本项目采用动态dlopen + 内存模拟的双轨方案:
1. 在初始化时先调用dlopen("libfile_cache_boost.so")尝试加载真实库;
2. 若加载成功,则通过dlsym获取各函数指针,使用真库运行;
3. 若失败,则自动降级为纯C++编写的std::unordered_map仿真引擎。仿真引擎的接口签名与真库完全一致,行为逻辑高保真,确保代码在任意HarmonyOS设备上都能编译通过并演示功能。
三、实战代码:FileCacheBoostNative.cpp核心实现
在entry/src/main/cpp下创建FileCacheBoostNative.cpp,包含如下关键逻辑:
- // 尝试加载真实库
- static void TryLoadRealSo() {
- static std::once_flag flag;
- std::call_once(flag, []() {
- g_soHandle = dlopen("libfile_cache_boost.so", RTLD_NOW);
- if (g_soHandle) {
- // 通过dlsym绑定所有API...
- g_useRealSo = true;
- } else {
- OH_LOG_WARN(LOG_APP, "Fallback to mock mode");
- }
- });
- }
- // 所有对外暴露的API实现都先检查g_useRealSo
- FileCacheBoost_ErrCode HMS_FileCacheBoost_Init(...) {
- TryLoadRealSo();
- if (g_useRealSo) return g_realInit(...);
- // 仿真引擎:记录路径,标记初始化
- ...
- }
复制代码
仿真引擎内部使用全局的std::unordered_map<std::string, MockCacheEntry>存储缓存项,插入、查询、删除均加锁保证线程安全。读取时动态malloc分配缓冲区,复制数据后返回指针,与真实库的GetObjectByKey行为一致。
四、复杂对象自定义序列化示例
假设我们需要缓存一个包含指针的动态图像结构体:- struct SimpleImage {
- int width;
- int height;
- int format;
- unsigned char *pixels; // 堆分配
- };
复制代码 序列化回调中,遍历pixels数组并通过writeFunc逐字节写出;反序列化时,先读取宽高等元数据,然后malloc分配pixels内存,通过readFunc填充数据。注意,读出的对象指针需由调用者负责释放。
五、ArkTS侧集成与效果演示
在ArkTS调用NDK的NAPI接口时,需要确保types目录下的index.d.ts声明了所有接口类型。UI层提供了“初始化面板”、“普通缓存写入/获取”、“复杂对象序列化存取”和“缓存池监控器”四个区域。点击“Add”调用NDK侧HMS_FileCacheBoost_AddObjectByKey将解码后的像素字节落盘;点击“Get”免解码直接读取,实现极速无感浏览。
通过此方案,开发者可在2in1设备上显著提升文件浏览的启动速度和滑动流畅度,同时利用权重淘汰机制保证热数据常驻缓存。对于非2in1环境,仿真引擎同样能完整模拟逻辑,便于前期开发调试。
完整项目源码已在鸿蒙极客社区开源,欢迎搜索“Preview Kit 通用文件缓存加速”获取。 |