Когда очистить кэш dir в Android?
У меня есть приложение, которое отображает фотографии из Интернета (витрина для дизайнерских работ). Я начинаю кешировать свой контент во внутреннем каталоге кеша, но контент приложения может занимать около 150 МБ в размере кеша. А что говорит андроид документация:
Вы всегда должны поддерживать файлы кэша самостоятельно и не выходить за разумные пределы, например, 1 МБ. Когда пользователь удаляет ваше приложение, эти файлы удаляются.
Поэтому я взглянул на приложение Currents (Galaxy Nexus) и размер кеша для приложения составляет 110 МБ. Но что странно, так это то, что приложения, такие как Google Currents и Google Maps, кэшируют контент в нечто, называемое (USB Storage Data):
Итак, что же это за "USB Storage Data", который использует предыдущее приложение. И если вы реализуете кеширование в своем приложении, вы зацикливаетесь на всех файлах вашего приложения в кеше, чтобы получать размер каждый раз, когда вам нужно что-то вставить, а затем сравнивать и очищать его? Или вы продолжаете кэшировать контент до тех пор, пока Android не решит очистить каталог кеша приложения?
Мне действительно интересно узнать, как обстоят дела с управлением кешем в Android или, по крайней мере, что другие приложения делают с большим контентом для кеширования.
5 ответов
Прежде чем перейти к вашему вопросу, вот краткое объяснение двух типов хранения:
кэш
Это специфичный для приложения каталог в файловой системе. Назначение этого каталога - хранить временные данные, которые могут понадобиться вашему приложению между сеансами, но, возможно, не жизненно важно хранить их вечно. Вы обычно получаете доступ к этому каталогу с Context.getCacheDir()
, Это будет отображаться как "Кэш" в настройках вашего приложения.
файлы
Как и каталог кеша, в вашем приложении также есть специальный каталог для хранения файлов. Файлы в этом каталоге будут существовать до тех пор, пока приложение явно не удалит их или приложение не будет удалено. Вы обычно получаете доступ к этому каталогу с Context.getFilesDir()
, Это может отображаться как различные вещи на экране информации о приложении, но на скриншоте это "Данные USB-накопителя".
ПРИМЕЧАНИЕ. Если вы хотите явно разместить на внешнем носителе (обычно на SD-карте), вы можете использовать Context.getExternalFilesDir(String type)
,
Различия
Оба каталога относятся только к вашему приложению (другие приложения не имеют доступа). Одно из различий между кешем и каталогом файлов заключается в том, что если системе не хватает памяти, первое место, куда она собирается освободить ресурсы, - это каталог кеша. Система не удалит данные из каталога файлов. Другое отличие состоит в том, что каталог кэша обычно можно очистить вручную с экрана информации о приложении. Каталог файлов, как правило, тоже может, но очистка каталога файлов также очистит каталог кэша.
Какой из них я использую?
Это зависит от того, насколько важны эти данные по сравнению с временем жизни вашего приложения. Если вам нужны данные только для одного сеанса и вы сомневаетесь, что вам когда-нибудь понадобится использовать эти данные снова, не используйте их. Просто держите это в памяти, пока вам это не понадобится. Если вы подозреваете, что вам нужно повторно использовать данные между несколькими сеансами, но вам не нужно хранить бумажную копию, используйте каталог кеша. Если вам нужны эти данные, независимо от того, что это, или если это достаточно большие данные, которые требуют постоянного хранения, используйте каталог files. Вот несколько примеров, которые я могу придумать:
- Кэш - недавно открытое письмо
- После открытия кэшируйте данные, чтобы, когда пользователь захочет снова прочитать это электронное письмо, он загружался мгновенно, а затем снова использовал сеть для извлечения тех же данных. Мне не нужно хранить это навсегда, потому что в конце концов пользователь будет закончен с электронной почтой.
- Файлы - вложение, загруженное из электронного письма.
- Это действие пользователя, который говорит: "Я хочу сохранить эти данные, чтобы я мог восстановить их, когда мне это понадобится". Поэтому поместите его в каталог файлов, поскольку я не хочу удалять этот файл, пока пользователь не захочет удалить его.
Когда я должен очистить каталог кеша?
От Context.getCacheDir()
Javadocs:
Примечание: вы не должны полагаться на систему, удаляющую эти файлы за вас; у вас всегда должен быть разумный максимум, например, 1 МБ, для объема пространства, которое вы используете с файлами кэша, и обрезать эти файлы при превышении этого пространства.
Он использует пример 1 МБ, но это может или не может быть разумным для вашего приложения. Независимо от этого, вам нужно установить жесткий максимум. Причина этого просто сводится к разработке ответственного приложения. Итак, когда вы должны проверить? Я бы рекомендовал проверять каждый раз, когда вы хотите поместить что-то в каталог кеша. Вот очень простой менеджер кеша:
public class CacheManager {
private static final long MAX_SIZE = 5242880L; // 5MB
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()) {
// Data doesn't exist
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;
}
}
Конечно, это может быть дорогостоящей операцией, поэтому вы должны планировать кэширование в фоновом потоке.
Кроме того, это может быть так сложно, как вам нужно. В моем примере я предполагаю, что все кэшированные файлы размещены в корне каталога кеша, поэтому я не проверяю потенциальные подкаталоги. Процедура удаления файлов также может стать более сложной, например, удаление файлов по самой старой дате доступа.
При принятии решения о кэшировании данных следует иметь в виду, что вам всегда нужно планировать случай, когда ваши кэшированные данные больше не существуют. Всегда имейте подпрограмму для извлечения данных внешними средствами, когда ваш кеш не имеет их в хранилище. Кроме того, всегда проверяйте свой кэш, прежде чем извлекать данные извне. Цель кэша - сократить сетевую активность, длительные процессы и предоставить отзывчивый пользовательский интерфейс в вашем приложении. Так что пользуйтесь им ответственно:)
Я думаю, лучший способ очистить кэш приложения после завершения активности, чтобы каждый раз очищать кэш при вызове новой активности.
поместите этот код в onDestroy() для очистки кэша приложения
@Override
protected void onDestroy() {
super.onDestroy();
try {
trimCache(this);
// Toast.makeText(this,"onDestroy " ,Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
Согласно документации, система очищает кэш, когда на устройстве недостаточно внутренней памяти. Начиная с API8 у вас есть метод getExternalCacheDir(), который я считаю полезным, поскольку я прочитал, что у вас может быть около 150 МБ данных, но недостатком внешнего кэша является то, что вам придется самостоятельно очищать каталог кэша, если он слишком велик.
Зависит от типа приложения:
- Некоторые приложения используют только отдельные сеансы и не нуждаются в запоминании каких-либо данных, поэтому вы можете очистить кеш, когда захотите (некоторые приложения даже делают это автоматически в своей активности onStop)
- Большинство приложений хранят ваши данные, потому что они запоминают ваши настройки, учетную запись, которую вы использовали для входа в систему,... В этом случае лучше очищать кэш только тогда, когда вы не часто используете приложение.
Также:
So i took a look at Chrome app (Galaxy Nexus) and the cache size for the application is 110 MB. But what wired is that applications like Google current & Google maps cache the content in something called (USB Storage Data) :
AFAIK, данные для хранения USB отличаются от использования кеша: хранилище предназначено для хранения информации, специфичной для программы (например, карты для приложения GPS), кеш используется для хранения информации, специфичной для пользователя (например, логины).
В случае карт Google: я предполагаю, что они хранят данные карт в USB-хранилище и сохраняют ваши настройки и историю поиска в кэше ==> данные карт относятся к конкретному приложению, параметры и история поиска зависят от пользователя
Я думаю, что идея кеша - написать на нем все, что вы захотите, и Android будет управлять его размером, если он станет слишком большим.
Следует помнить, что вы можете записывать файлы в кеш, но всегда проверяет, сохранен ли файл при попытке доступа к нему. И пусть андроид управляет кешем.