0
# Data Management and Maintenance
1
2
Comprehensive data management including backup/restore operations, file validation, storage cleanup, and performance optimization. MMKV provides extensive tools for maintaining data integrity and optimizing storage usage.
3
4
## Capabilities
5
6
### Key Management and Queries
7
8
Manage and query keys within MMKV instances.
9
10
```java { .api }
11
/**
12
* Check whether or not MMKV contains the key.
13
* @param key The key of the value
14
* @return true if key exists, false otherwise
15
*/
16
public boolean containsKey(String key);
17
18
/**
19
* Get all keys.
20
* @return Array of all keys, or null if empty
21
*/
22
public String[] allKeys();
23
24
/**
25
* Get all non-expired keys. Note that this call has costs.
26
* @return Array of all non-expired keys, or null if empty
27
*/
28
public String[] allNonExpireKeys();
29
30
/**
31
* Get the total count of all keys.
32
* @return The total count of all keys
33
*/
34
public long count();
35
36
/**
37
* Get the total count of all non-expired keys. Note that this call has costs.
38
* @return The total count of all non-expired keys
39
*/
40
public long countNonExpiredKeys();
41
```
42
43
**Usage Example:**
44
45
```java
46
MMKV kv = MMKV.defaultMMKV();
47
48
// Add some data
49
kv.encode("user_name", "Alice");
50
kv.encode("user_age", 25);
51
kv.encode("temp_data", "temporary", MMKV.ExpireInMinute);
52
53
// Check key existence
54
if (kv.containsKey("user_name")) {
55
String name = kv.decodeString("user_name", "");
56
Log.d("MMKV", "User name: " + name);
57
}
58
59
// Get all keys
60
String[] allKeys = kv.allKeys();
61
if (allKeys != null) {
62
Log.d("MMKV", "Total keys: " + allKeys.length);
63
for (String key : allKeys) {
64
Log.d("MMKV", "Key: " + key);
65
}
66
}
67
68
// Get key counts
69
long totalCount = kv.count();
70
long nonExpiredCount = kv.countNonExpiredKeys();
71
Log.d("MMKV", "Total: " + totalCount + ", Non-expired: " + nonExpiredCount);
72
73
// Get only non-expired keys
74
String[] activeKeys = kv.allNonExpireKeys();
75
Log.d("MMKV", "Active keys: " + (activeKeys != null ? activeKeys.length : 0));
76
```
77
78
### Value Size Information
79
80
Get detailed information about stored values and their memory usage.
81
82
```java { .api }
83
/**
84
* Get the actual size consumption of the key's value.
85
* Note: might be a little bigger than value's length.
86
* @param key The key of the value
87
* @return Size in bytes of the stored value
88
*/
89
public int getValueSize(String key);
90
91
/**
92
* Get the actual size of the key's value. String's length or byte[]'s length, etc.
93
* @param key The key of the value
94
* @return Actual size of the value data
95
*/
96
public int getValueActualSize(String key);
97
98
/**
99
* Get the size of the underlying file. Align to the disk block size, typically 4K for an Android device.
100
* @return Total file size in bytes
101
*/
102
public long totalSize();
103
104
/**
105
* Get the actual used size of the MMKV instance.
106
* This size might increase and decrease as MMKV doing insertion and full write back.
107
* @return Actual used size in bytes
108
*/
109
public long actualSize();
110
```
111
112
**Usage Example:**
113
114
```java
115
// Store various types of data
116
kv.encode("short_text", "Hello");
117
kv.encode("long_text", "This is a much longer string that will take more space");
118
kv.encode("large_data", new byte[10240]); // 10KB byte array
119
120
// Analyze storage usage
121
String[] keys = kv.allKeys();
122
if (keys != null) {
123
for (String key : keys) {
124
int storageSize = kv.getValueSize(key);
125
int actualSize = kv.getValueActualSize(key);
126
Log.d("MMKV", String.format("Key: %s, Storage: %d bytes, Actual: %d bytes",
127
key, storageSize, actualSize));
128
}
129
}
130
131
// Get overall file statistics
132
long totalFileSize = kv.totalSize();
133
long usedSize = kv.actualSize();
134
double utilizationRatio = (double) usedSize / totalFileSize;
135
136
Log.d("MMKV", String.format("File size: %d KB, Used: %d KB, Utilization: %.1f%%",
137
totalFileSize / 1024, usedSize / 1024, utilizationRatio * 100));
138
```
139
140
### Data Removal Operations
141
142
Remove individual keys or clear entire MMKV instances.
143
144
```java { .api }
145
/**
146
* Remove a single key-value pair.
147
* @param key The key to remove
148
*/
149
public void removeValueForKey(String key);
150
151
/**
152
* Batch remove some keys from the MMKV instance.
153
* @param arrKeys The keys to be removed
154
*/
155
public void removeValuesForKeys(String[] arrKeys);
156
157
/**
158
* Clear all the key-values inside the MMKV instance.
159
* The data file will be trimmed down to pageSize, and some sync operations will be called.
160
* If you do not want to trim the file, use clearAllWithKeepingSpace() instead for better performance.
161
*/
162
public void clearAll();
163
164
/**
165
* Faster clearAll() implementation.
166
* The file size is kept as previous for later use.
167
*/
168
public void clearAllWithKeepingSpace();
169
```
170
171
**Usage Example:**
172
173
```java
174
// Remove single key
175
kv.removeValueForKey("temp_data");
176
177
// Remove multiple keys at once
178
String[] keysToRemove = {"old_cache", "expired_token", "temp_config"};
179
kv.removeValuesForKeys(keysToRemove);
180
181
// Clear all data with file trimming (slower but saves disk space)
182
kv.clearAll();
183
184
// Clear all data keeping file size (faster, good for temporary clearing)
185
MMKV tempKv = MMKV.mmkvWithID("temp_storage");
186
tempKv.clearAllWithKeepingSpace(); // Faster for frequent clear operations
187
188
// Example: Cleanup old data based on patterns
189
String[] allKeys = kv.allKeys();
190
if (allKeys != null) {
191
List<String> expiredKeys = new ArrayList<>();
192
for (String key : allKeys) {
193
if (key.startsWith("cache_") && isExpired(key)) {
194
expiredKeys.add(key);
195
}
196
}
197
if (!expiredKeys.isEmpty()) {
198
kv.removeValuesForKeys(expiredKeys.toArray(new String[0]));
199
Log.d("MMKV", "Removed " + expiredKeys.size() + " expired cache keys");
200
}
201
}
202
```
203
204
### File Management and Optimization
205
206
Optimize file usage and perform maintenance operations.
207
208
```java { .api }
209
/**
210
* The totalSize() of an MMKV instance won't reduce after deleting key-values,
211
* call this method after lots of deleting if you care about disk usage.
212
* Note that clearAll() has a similar effect.
213
*/
214
public void trim();
215
216
/**
217
* Save all mmap memory to file synchronously.
218
* You don't need to call this, really, I mean it.
219
* Unless you worry about the device running out of battery.
220
*/
221
public void sync();
222
223
/**
224
* Save all mmap memory to file asynchronously.
225
* No need to call this unless you worry about the device running out of battery.
226
*/
227
public void async();
228
229
/**
230
* Clear memory cache of the MMKV instance.
231
* You can call it on memory warning.
232
* Any subsequent call to the MMKV instance will trigger all key-values loading from the file again.
233
*/
234
public void clearMemoryCache();
235
```
236
237
**Usage Example:**
238
239
```java
240
// Trim file after bulk deletions
241
long sizeBefore = kv.totalSize();
242
// ... perform many deletions ...
243
kv.trim();
244
long sizeAfter = kv.totalSize();
245
Log.d("MMKV", "File size reduced by " + (sizeBefore - sizeAfter) + " bytes");
246
247
// Force synchronization before critical operations
248
kv.sync(); // Synchronous - blocks until complete
249
// Or use asynchronous version
250
kv.async(); // Non-blocking
251
252
// Handle memory pressure
253
@Override
254
public void onTrimMemory(int level) {
255
super.onTrimMemory(level);
256
switch (level) {
257
case TRIM_MEMORY_MODERATE:
258
case TRIM_MEMORY_RUNNING_MODERATE:
259
// Clear non-critical MMKV caches
260
cacheMmkv.clearMemoryCache();
261
break;
262
case TRIM_MEMORY_COMPLETE:
263
case TRIM_MEMORY_RUNNING_CRITICAL:
264
// Clear all MMKV memory caches
265
kv.clearMemoryCache();
266
cacheMmkv.clearMemoryCache();
267
break;
268
}
269
}
270
```
271
272
### File Validation and Integrity
273
274
Validate MMKV files and check data integrity.
275
276
```java { .api }
277
/**
278
* Check whether the MMKV file is valid or not.
279
* Note: Don't use this to check the existence of the instance, the result is undefined on nonexistent files.
280
* @param mmapID The unique ID of the MMKV instance
281
* @return true if file is valid, false otherwise
282
*/
283
public static boolean isFileValid(String mmapID);
284
285
/**
286
* Check whether the MMKV file is valid or not on customize folder.
287
* @param mmapID The unique ID of the MMKV instance
288
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
289
* @return true if file is valid, false otherwise
290
*/
291
public static boolean isFileValid(String mmapID, String rootPath);
292
293
/**
294
* Check existence of the MMKV file.
295
* @param mmapID The unique ID of the MMKV instance
296
* @return true if file exists, false otherwise
297
*/
298
public static boolean checkExist(String mmapID);
299
300
/**
301
* Check existence of the MMKV file.
302
* @param mmapID The unique ID of the MMKV instance
303
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
304
* @return true if file exists, false otherwise
305
*/
306
public static boolean checkExist(String mmapID, String rootPath);
307
```
308
309
**Usage Example:**
310
311
```java
312
// Check if MMKV files exist and are valid
313
String[] instanceIds = {"user_data", "cache_data", "settings"};
314
315
for (String instanceId : instanceIds) {
316
boolean exists = MMKV.checkExist(instanceId);
317
boolean isValid = exists && MMKV.isFileValid(instanceId);
318
319
Log.d("MMKV", String.format("Instance %s: exists=%b, valid=%b",
320
instanceId, exists, isValid));
321
322
if (exists && !isValid) {
323
Log.w("MMKV", "Corrupted MMKV file detected: " + instanceId);
324
// Handle corruption - maybe restore from backup or recreate
325
handleCorruptedFile(instanceId);
326
}
327
}
328
329
private void handleCorruptedFile(String instanceId) {
330
// Remove corrupted file
331
boolean removed = MMKV.removeStorage(instanceId);
332
if (removed) {
333
Log.d("MMKV", "Removed corrupted file: " + instanceId);
334
// Recreate with default values
335
MMKV newInstance = MMKV.mmkvWithID(instanceId);
336
initializeDefaultValues(newInstance);
337
}
338
}
339
```
340
341
### Storage Removal
342
343
Permanently remove MMKV storage files.
344
345
```java { .api }
346
/**
347
* Remove the storage of the MMKV, including the data file & meta file (.crc).
348
* Note: the existing instance (if any) will be closed & destroyed.
349
* @param mmapID The unique ID of the MMKV instance
350
* @return true if removal was successful, false otherwise
351
*/
352
public static boolean removeStorage(String mmapID);
353
354
/**
355
* Remove the storage of the MMKV, including the data file & meta file (.crc).
356
* Note: the existing instance (if any) will be closed & destroyed.
357
* @param mmapID The unique ID of the MMKV instance
358
* @param rootPath The folder of the MMKV instance, defaults to $(FilesDir)/mmkv
359
* @return true if removal was successful, false otherwise
360
*/
361
public static boolean removeStorage(String mmapID, String rootPath);
362
```
363
364
**Usage Example:**
365
366
```java
367
// Clean up temporary storage
368
boolean tempRemoved = MMKV.removeStorage("temp_cache");
369
if (tempRemoved) {
370
Log.d("MMKV", "Temporary cache storage removed");
371
}
372
373
// Remove storage with custom path
374
File customDir = new File(getExternalFilesDir(null), "custom_mmkv");
375
boolean customRemoved = MMKV.removeStorage("custom_data", customDir.getAbsolutePath());
376
377
// Bulk cleanup of old instances
378
String[] oldInstances = {"old_cache_v1", "deprecated_settings", "temp_data_2023"};
379
int removedCount = 0;
380
for (String instanceId : oldInstances) {
381
if (MMKV.removeStorage(instanceId)) {
382
removedCount++;
383
}
384
}
385
Log.d("MMKV", "Removed " + removedCount + " old storage instances");
386
```
387
388
### Backup and Restore Operations
389
390
Comprehensive backup and restore functionality for data protection and migration.
391
392
```java { .api }
393
/**
394
* Backup one MMKV instance to dstDir.
395
* @param mmapID The MMKV ID to backup
396
* @param dstDir The backup destination directory
397
* @param rootPath The customize root path of the MMKV, if null then backup from the root dir of MMKV
398
* @return true if backup was successful, false otherwise
399
*/
400
public static boolean backupOneToDirectory(String mmapID, String dstDir, String rootPath);
401
402
/**
403
* Restore one MMKV instance from srcDir.
404
* @param mmapID The MMKV ID to restore
405
* @param srcDir The restore source directory
406
* @param rootPath The customize root path of the MMKV, if null then restore to the root dir of MMKV
407
* @return true if restore was successful, false otherwise
408
*/
409
public static boolean restoreOneMMKVFromDirectory(String mmapID, String srcDir, String rootPath);
410
411
/**
412
* Backup all MMKV instances from default root dir to dstDir.
413
* @param dstDir The backup destination directory
414
* @return Count of MMKV instances successfully backed up
415
*/
416
public static long backupAllToDirectory(String dstDir);
417
418
/**
419
* Restore all MMKV instances from srcDir to default root dir.
420
* @param srcDir The restore source directory
421
* @return Count of MMKV instances successfully restored
422
*/
423
public static long restoreAllFromDirectory(String srcDir);
424
```
425
426
**Usage Example:**
427
428
```java
429
// Backup individual instance
430
File backupDir = new File(getExternalFilesDir(null), "mmkv_backup");
431
if (!backupDir.exists()) {
432
backupDir.mkdirs();
433
}
434
435
boolean backupSuccess = MMKV.backupOneToDirectory(
436
"user_data",
437
backupDir.getAbsolutePath(),
438
null
439
);
440
441
if (backupSuccess) {
442
Log.d("MMKV", "User data backed up successfully");
443
} else {
444
Log.e("MMKV", "Failed to backup user data");
445
}
446
447
// Restore individual instance
448
File restoreDir = new File(getExternalFilesDir(null), "mmkv_backup");
449
boolean restoreSuccess = MMKV.restoreOneMMKVFromDirectory(
450
"user_data",
451
restoreDir.getAbsolutePath(),
452
null
453
);
454
455
// Backup all instances
456
long backedUpCount = MMKV.backupAllToDirectory(backupDir.getAbsolutePath());
457
Log.d("MMKV", "Backed up " + backedUpCount + " MMKV instances");
458
459
// Restore all instances
460
long restoredCount = MMKV.restoreAllFromDirectory(restoreDir.getAbsolutePath());
461
Log.d("MMKV", "Restored " + restoredCount + " MMKV instances");
462
463
// Automated backup strategy
464
private void performRegularBackup() {
465
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
466
String timestamp = sdf.format(new Date());
467
468
File backupDir = new File(getExternalFilesDir(null), "mmkv_backup_" + timestamp);
469
backupDir.mkdirs();
470
471
long backupCount = MMKV.backupAllToDirectory(backupDir.getAbsolutePath());
472
473
if (backupCount > 0) {
474
Log.d("MMKV", "Backup completed: " + backupCount + " instances");
475
// Keep only last 5 backups
476
cleanupOldBackups();
477
}
478
}
479
```
480
481
### Data Import Operations
482
483
Import data from other MMKV instances or SharedPreferences.
484
485
```java { .api }
486
/**
487
* Import all key-value items from src MMKV instance.
488
* @param src Source MMKV instance to import from
489
* @return Count of items imported
490
*/
491
public long importFrom(MMKV src);
492
493
/**
494
* Atomically migrate all key-values from an existent SharedPreferences to the MMKV instance.
495
* @param preferences The SharedPreferences to import from
496
* @return The total count of key-values imported
497
*/
498
public int importFromSharedPreferences(SharedPreferences preferences);
499
```
500
501
**Usage Example:**
502
503
```java
504
// Migrate from SharedPreferences to MMKV
505
SharedPreferences oldPrefs = getSharedPreferences("old_settings", MODE_PRIVATE);
506
MMKV newKv = MMKV.mmkvWithID("migrated_settings");
507
508
int migratedCount = newKv.importFromSharedPreferences(oldPrefs);
509
Log.d("MMKV", "Migrated " + migratedCount + " settings from SharedPreferences");
510
511
// Merge data from multiple MMKV instances
512
MMKV masterKv = MMKV.mmkvWithID("master_data");
513
MMKV tempKv1 = MMKV.mmkvWithID("temp_data_1");
514
MMKV tempKv2 = MMKV.mmkvWithID("temp_data_2");
515
516
long imported1 = masterKv.importFrom(tempKv1);
517
long imported2 = masterKv.importFrom(tempKv2);
518
519
Log.d("MMKV", "Imported " + (imported1 + imported2) + " items to master instance");
520
521
// Clean up temporary instances after import
522
MMKV.removeStorage("temp_data_1");
523
MMKV.removeStorage("temp_data_2");
524
```
525
526
### Instance Lifecycle Management
527
528
Properly manage MMKV instance lifecycle and resources.
529
530
```java { .api }
531
/**
532
* Call this method if the MMKV instance is no longer needed in the near future.
533
* Any subsequent call to any MMKV instances with the same ID is undefined behavior.
534
*/
535
public void close();
536
```
537
538
**Usage Example:**
539
540
```java
541
public class DataManager {
542
private MMKV cacheKv;
543
private MMKV userKv;
544
545
public void initialize() {
546
cacheKv = MMKV.mmkvWithID("app_cache");
547
userKv = MMKV.mmkvWithID("user_data");
548
}
549
550
public void cleanup() {
551
// Close instances when no longer needed
552
if (cacheKv != null) {
553
cacheKv.close();
554
cacheKv = null;
555
}
556
557
if (userKv != null) {
558
userKv.close();
559
userKv = null;
560
}
561
}
562
563
// Call during app lifecycle events
564
@Override
565
protected void onDestroy() {
566
super.onDestroy();
567
cleanup();
568
}
569
}
570
```