I have a quite large datastructure that I would like to load (from the bundle to memory). My requirements are the following:
- This should take place in the background (non-blocking), not delaying the app starting time and not freezing the app after it loaded.
- The data is not required right away, so there is plenty of time to load it.
- Data loading should start as soon as possible.
Current test
For now I have something quite basic but it doesn't fit my requirements. It looks like this:
// `data.ts` File containing my maps
const testMap: Map<string, Content> = new Map([
["k1_2", {"a": 1, "b": 2}],
["k10_20", {"a": 10, "b": 20}],
]);
import React, { useState } from 'react';
import { Text } from 'react-native';
import { map } from './data';
const TEST_A = 500;
const TEST_B = 100;
function TestLoadingDataStructure() {
const [duration, setDuration] = useState('-');
const [valid, setValid] = useState(false);
function runTest() {
const startTime = new Date();
const values = testMap.get(`k${TEST_A}_${TEST_B}`);
const endTime = new Date();
const duration = endTime - startTime;
if (duration > 1000) {
setDuration(`${duration / 1000} seconds`);
} else {
setDuration(`${duration} ms.`);
}
setValid(values.a * values.b === TEST_A * TEST_B);
}
return (
<Text onPress={runTest}>
Test, durée ={' '}
<Text
style={{ color: valid ? 'green' : 'red' }}
>
{duration}
</Text>
</Text>
);
}
If you use this component and click the text, the first time you press it it will take a long time (on my phone it takes approximately 5 seconds). The second time I press it, it takes less than 1 ms.
My goal is to have this take 1ms even the first time. For this I need to load my data before the component loads (I guess?). I could do this by adding this line at the top of my component file:
testMap.get(`k1_1`);
function TestLoadingDataStructure() {...}
But doing that slows down the app loading, so I though this could be solved by loading dynamically, like so:
setTimeout(() => {
testMap.get(`k1_1`);
}, 1000);
But this freezes the application when the timeout triggers.
The questions
- Is there a nice way of loading the data in the background?
- Is storing the data in a plain text file a good idea?
- Any other suggestion is welcome, I'm realy uncertain about all this and I don't know what to search for.
Test data
If you want some data that looks a bit like the real one (shape and size) you can test with this:
echo "export const testMap = new Map([" > data.ts
for i in {1..1000}
do for j in {1..200}
do echo "\t[\"k${i}_${j}\", { \"a\": $i, \"b\": $j }],"
done
done >> data.ts
echo "]);" >> data.ts
CodePudding user response:
As discussed in the comments, storing the static data in a file that has to be parsed in full before it can be used (e.g. a JavaScript/TypeScript module, or a JSON file in the bundle) does not sound like a great idea.
Instead you'll want a format that doesn't need to be read to memory to access a single key, and an SQLite database fits that bill well. You can use e.g. react-native-sqlite-storage to access a pre-populated database.
If, for some reason, you couldn't use SQLite, you could of course roll a database format of your own (e.g. JSONL/ND-JSON might be a good record format), but it'll be slower and more work for you.