Перш ніж перейти до вашого запитання, ось коротке пояснення двох типів сховищ:
Кеш
Це каталог для конкретної програми у файловій системі. Метою цього каталогу є зберігання тимчасових даних, які може знадобитися для зберігання вашої програми між сеансами, але може не мати життєвого значення для збереження їх назавжди. Зазвичай ви отримуєте доступ до цього каталогу за допомогою Context.getCacheDir()
. Це відображатиметься як "Кеш" у налаштуваннях програми.
Файли
Як і каталог кеш-пам’яті, у вашому додатку також є спеціальний каталог для зберігання файлів. Файли в цьому каталозі існуватимуть, поки програма явно їх не видалить або програму не буде видалено. Зазвичай ви отримуєте доступ до цього каталогу за допомогою Context.getFilesDir()
. Це може відображатися на екрані інформації про програму як різне, але на вашому скріншоті це "Дані USB-накопичувача".
ПРИМІТКА. Якщо ви хочете чітко розмістити на зовнішньому носії (як правило, SD-картці), ви можете використовувати Context.getExternalFilesDir(String type)
.
Різниця
Обидва каталоги характерні лише для вашої програми (інші програми не мають доступу). Однією з відмінностей між каталогом кеш-пам’яті та файлів є те, що якщо в системі мало місця, перше місце, яке вона збирається звільнити, - з вашого каталогу кеш-пам’яті. Система не буде очищати будь-які дані з каталогу файлів. Інша відмінність полягає в тому, що каталог кеш-пам’яті зазвичай можна очистити вручну з екрана інформації про програму. Каталог файлів зазвичай також може, але очищення каталогу файлів також очистить каталог кешу.
Який я використовую?
Це залежить від того, наскільки ці дані порівнюються із часом життя вашого додатка. Якщо вам потрібні дані лише для одного сеансу, і ви сумніваєтеся, що вам коли-небудь доведеться використовувати ці дані знову, тоді не використовуйте жодного. Просто зберігайте його в пам’яті, поки вам це не знадобиться. Якщо ви підозрюєте, що вам доведеться повторно використовувати дані між кількома сеансами, але вам не потрібно зберігати друковану копію, використовуйте каталог кешу. Якщо ви повинні мати ці дані незалежно від того, або якщо це досить великі дані, які потребують постійного зберігання, використовуйте каталог файлів. Ось кілька прикладів, про які я можу згадати:
- Кеш - нещодавно відкритий електронний лист
- Після відкриття кешуйте дані, щоб, коли користувач захоче прочитати цей електронний лист, він миттєво завантажувався, а не знову використовував мережу для отримання тих самих даних. Мені не потрібно зберігати це назавжди, тому що врешті-решт користувач закінчить з електронною поштою.
- Файли - вкладення, завантажене з електронного листа
- Це дія користувача, який каже: "Я хочу зберегти ці дані, щоб я міг повернути їх назад, коли мені це потрібно". Тому помістіть його в каталог файлів, оскільки я ніколи не хочу видаляти цей файл, поки користувач не захоче його видалити.
Коли слід очищати каталог кешу?
З Context.getCacheDir()
javadocs:
Примітка: ви не повинні покладатися на те, що система видалить ці файли за вас; ви завжди повинні мати розумний максимум, наприклад 1 МБ, для обсягу місця, який ви займаєте з кеш-файлами, і обрізати ці файли, коли перевищуєте цей простір.
Він використовує приклад 1 Мб, але це може бути або не бути розумним для вашого додатка. Незалежно від цього, вам потрібно встановити жорсткий максимум. Причина цього просто зводиться до розробки відповідального додатка. То коли слід перевіряти? Я б рекомендував перевіряти кожен раз, коли ви хочете помістити щось у каталог кешу. Ось дуже простий кеш-менеджер:
public class CacheManager {
private static final long MAX_SIZE = 5242880L;
private CacheManager() {
}
public static void cacheData(Context context, byte[] data, String name) throws IOException {
File cacheDir = context.getCacheDir();
long size = getDirSize(cacheDir);
long newSize = data.length + size;
if (newSize > MAX_SIZE) {
cleanDir(cacheDir, newSize - MAX_SIZE);
}
File file = new File(cacheDir, name);
FileOutputStream os = new FileOutputStream(file);
try {
os.write(data);
}
finally {
os.flush();
os.close();
}
}
public static byte[] retrieveData(Context context, String name) throws IOException {
File cacheDir = context.getCacheDir();
File file = new File(cacheDir, name);
if (!file.exists()) {
return null;
}
byte[] data = new byte[(int) file.length()];
FileInputStream is = new FileInputStream(file);
try {
is.read(data);
}
finally {
is.close();
}
return data;
}
private static void cleanDir(File dir, long bytes) {
long bytesDeleted = 0;
File[] files = dir.listFiles();
for (File file : files) {
bytesDeleted += file.length();
file.delete();
if (bytesDeleted >= bytes) {
break;
}
}
}
private static long getDirSize(File dir) {
long size = 0;
File[] files = dir.listFiles();
for (File file : files) {
if (file.isFile()) {
size += file.length();
}
}
return size;
}
}
Звичайно, це може бути дорогою операцією, тому вам слід спланувати кешування на фоновому потоці.
Крім того, це може бути настільки складно, наскільки вам це потрібно. У своєму прикладі я припускаю, що всі кешовані файли розміщені в корені каталогу кеш-пам'яті, тому я не перевіряю наявність потенційних підкаталогів. Процедура видалення файлів також може стати більш складною, наприклад, видалення файлів до найдавнішої дати доступу.
Одне, про що слід пам’ятати, вирішуючи кешувати дані, - це те, що вам потрібно завжди планувати випадок, коли ваші кешовані дані більше не існують. Завжди встановіть процедуру отримання даних зовнішніми засобами, коли у кеш-пам’яті їх немає. Так само завжди перевіряйте кеш-пам’ять перед тим, як отримувати дані зовні. Призначення кеша - зменшити мережеву активність, тривалі процеси та забезпечити адаптивний інтерфейс у вашому додатку. Тож використовуйте відповідально :)