Realm本地数据库读写大对象过慢致React Native应用卡顿求助
问题描述
需要在10-20秒内将BLE监听器获取的6000个对象写入Realm数据库,目前尝试一次性写入全部对象速度极慢,改为批量写入200个对象后仍耗时较长,且读写过程中React Native应用出现卡顿,寻求优化方案。
BLE数据处理代码
let a = []; let arrayBuffer = []; const handleNotificationUpdate = data => { if (data) { let byteArray = data.value; const hexArray = byteArrayToHexArray(byteArray); const packets = separatePackets(hexArray); const decimalArrays = packets.map(packet => packet.map(hex => parseInt(hex, 16))); const extractedValues = extractValuesFromPackets(decimalArrays); // Adding activityType and currentTime to objects const currentDate = new Date(); const options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true, timeZone: 'Asia/Karachi', // Pakistan timezone }; const currentTime = currentDate.toLocaleString('en-PK', options); extractedValues.forEach(obj => { if (!obj.hasOwnProperty('activityType')) { obj.activityType = 1; } obj.currentTime = currentTime; }); // Filter out objects with activityType undefined const filteredValues = extractedValues.filter(obj => obj.activityType !== undefined && obj.packetEndHeader !== undefined); arrayBuffer.push(filteredValues); handleArrayBuffer(); a = filteredValues; console.log(arrayBuffer.length); } }; const handleArrayBuffer = () => { if (arrayBuffer.length === 200) { console.log('000000000'); insertDataIntoRealm(arrayBuffer); arrayBuffer = []; } };
Realm操作代码
import Realm from 'realm'; const Array2Schema = { name: 'Array2', properties: { activityType: 'int', currentTime: 'string', greenLed1Counts: 'int[]', greenLed2Counts: 'int[]', irLedCounts: 'int[]', outputFormat: 'int', packetEndHeader: 'int', packetStartHeader: 'int', redLedCounts: 'int[]', temperatureSensor: 'int[]', time: 'int[]', xAxisReading: 'int[]', yAxisReading: 'int[]', zAxisReading: 'int[]', }, }; const Array1Schema = { name: 'Array1', properties: { array2: 'Array2[]', }, }; const openRealm = async () => { return Realm.open({ schema: [Array2Schema, Array1Schema], schemaVersion: 1, }); }; const insertDataIntoRealm = async (arrayData) => { try { const realm = await openRealm(); realm.write(() => { arrayData.forEach((array2Items) => { const array1 = realm.create('Array1', {}); array2Items.forEach((item) => { const array2 = realm.create('Array2', item); array1.array2.push(array2); }); }); }); realm.close(); } catch (error) { console.log('Error:', error); } }; export { insertDataIntoRealm, openRealm };
优化方案
以下是针对性能和卡顿问题的具体优化点:
1. 复用Realm实例,避免频繁打开/关闭
每次调用insertDataIntoRealm重新打开和关闭Realm会产生巨大开销,改成单例模式复用实例:
// Realm文件中修改openRealm为单例 let realmInstance = null; const openRealm = async () => { if (realmInstance && !realmInstance.isClosed) { return realmInstance; } realmInstance = await Realm.open({ schema: [Array2Schema, Array1Schema], schemaVersion: 1, }); return realmInstance; }; // 移除insertDataIntoRealm中的realm.close(),仅在应用退出时关闭实例 const insertDataIntoRealm = async (arrayData) => { try { const realm = await openRealm(); // ... 写入逻辑 ... // realm.close(); // 注释关闭操作 } catch (error) { console.log('Error:', error); } };
2. 使用异步写入避免阻塞主线程
同步realm.write()会阻塞UI线程导致卡顿,改用异步的realm.writeAsync():
const insertDataIntoRealm = async (arrayData) => { try { const realm = await openRealm(); await realm.writeAsync(() => { arrayData.forEach((array2Items) => { const array1 = realm.create('Array1', {}); // 优化:直接赋值数组替代逐个push,减少操作次数 array1.array2 = array2Items.map(item => realm.create('Array2', item)); }); }); } catch (error) { console.log('Error:', error); } };
3. 简化Schema设计,减少不必要的嵌套
如果Array1仅用于包裹Array2数组,无其他业务属性,可直接存储Array2对象,减少一层嵌套开销:
// Realm文件中移除Array1Schema,修改openRealm const openRealm = async () => { return Realm.open({ schema: [Array2Schema], schemaVersion: 2, // 升级版本号 }); }; // 简化写入逻辑,直接批量创建Array2对象 const insertDataIntoRealm = async (objects) => { try { const realm = await openRealm(); await realm.writeAsync(() => { // 批量创建比循环逐个create性能提升显著 realm.create('Array2', objects, true); // true表示允许更新重复对象,按需调整 }); } catch (error) { console.log('Error:', error); } }; // 对应修改BLE数据处理中的arrayBuffer逻辑,直接存储单个对象而非数组 const handleNotificationUpdate = data => { // ... 其他逻辑 ... // 替换arrayBuffer.push(filteredValues)为: filteredValues.forEach(item => arrayBuffer.push(item)); }; const handleArrayBuffer = () => { if (arrayBuffer.length >= 200) { // 取出前200个对象批量写入 const batch = arrayBuffer.splice(0, 200); insertDataIntoRealm(batch); } };
4. 优化数据预处理逻辑
- 缓存时间格式化配置,避免重复创建:
// 把timeOptions提到函数外部缓存 const timeOptions = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true, timeZone: 'Asia/Karachi', }; const handleNotificationUpdate = data => { if (data) { // ... 其他逻辑 ... const currentTime = new Date().toLocaleString('en-PK', timeOptions); // ... 其他逻辑 ... } };
- 移除不必要的
console.log,生产环境日志会拖慢性能。
5. 调整批量写入粒度
根据设备性能调整批量大小(如尝试500个对象/批),平衡写入效率和内存占用。
内容的提问来源于stack exchange,提问作者Hamza Qayyum
相关产品推荐
相关产品推荐

