Коли очистити папку кешу в Android?


77

У мене є програма, яка відображає картинки з Інтернету (вітрина для дизайнерських робіт). Я починаю кешувати свій вміст у каталозі внутрішнього кешу, але вміст програми може зайняти близько 150 МБ кешу. І що говорить андроїд-документація:

Ви завжди повинні самостійно підтримувати файли кеш-пам’яті та дотримуватися розумного обмеженого місця, такого як 1 МБ. Коли користувач видаляє вашу програму, ці файли видаляються.

Тож я подивився додаток Currents (Galaxy Nexus), і розмір кешу для програми становить 110 МБ. Але дивно те, що такі програми, як Google Currents і Google Maps, кешують вміст у щось, що називається (USB Storage Data):

введіть тут опис зображення

То що це за „Дані зберігання USB”, які використовує попередня програма. І якщо ви застосуєте кешування у своїй програмі, чи циклюєте всі файли ваших програм у кеші, щоб отримати розмір кожного разу, коли вам потрібно щось вставити, а потім порівняти та очистити? Або ви продовжуєте кешувати вміст до тих пір, поки Android не вирішить час очистити якийсь каталог кешу програм?

Мені справді цікаво дізнатись, яким є потік управління кеш-пам’яттю в Android, або хоча б те, що інші програми роблять із великим вмістом для кешування.


Припускаю, що дані накопичувача USB - це кеш, збережений у SD. На мою думку, розмір кеш-пам’яті повинен обирати кінцевий користувач у процесі вподобання, видаляючи останні файли, до яких здійснювався доступ, щоб зберегти обмеження.
Даніель Аргуеллес,

5
У комп’ютерних науках є лише дві важкі речі: скасування кешу та імена. - Phil Karlton
msanford

1
@msanford Ти знаєш, що складніше? Закриття vim ...
varun

Відповіді:


205

Перш ніж перейти до вашого запитання, ось коротке пояснення двох типів сховищ:

Кеш

Це каталог для конкретної програми у файловій системі. Метою цього каталогу є зберігання тимчасових даних, які може знадобитися для зберігання вашої програми між сеансами, але може не мати життєвого значення для збереження їх назавжди. Зазвичай ви отримуєте доступ до цього каталогу за допомогою 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; // 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;
    }
}

Звичайно, це може бути дорогою операцією, тому вам слід спланувати кешування на фоновому потоці.

Крім того, це може бути настільки складно, наскільки вам це потрібно. У своєму прикладі я припускаю, що всі кешовані файли розміщені в корені каталогу кеш-пам'яті, тому я не перевіряю наявність потенційних підкаталогів. Процедура видалення файлів також може стати більш складною, наприклад, видалення файлів до найдавнішої дати доступу.

Одне, про що слід пам’ятати, вирішуючи кешувати дані, - це те, що вам потрібно завжди планувати випадок, коли ваші кешовані дані більше не існують. Завжди встановіть процедуру отримання даних зовнішніми засобами, коли у кеш-пам’яті їх немає. Так само завжди перевіряйте кеш-пам’ять перед тим, як отримувати дані зовні. Призначення кеша - зменшити мережеву активність, тривалі процеси та забезпечити адаптивний інтерфейс у вашому додатку. Тож використовуйте відповідально :)


Що робити, якщо у мене є програма, яка вимагає м’якого зберігання великих файлів? Чи повинен я просто встановити кеш дійсно високим і не нести відповідальності через специфікацію чи зберігання у файлі filesDir і знайти спосіб видалення файлу звідти?
hipkiss

2
@hipkiss розмір кеш-пам’яті буде відрізнятися залежно від їхніх потреб. Встановіть максимум на те, що вважаєте розумним для вашого додатка.
Джейсон Робінсон,

@JasonRobinson чи існує обмеження максимального розміру каталогу кеш-пам’яті, або програма може містити стільки даних (скажімо, 500 МБ), скільки хоче?
Diffy

@Diffy Наскільки я знаю, цього немає, але я точно не знаю.
Джейсон Робінсон,

@JasonRobinson У мене є одне запитання. Я створюю додаток електронної бібліотеки, якому потрібно отримати доступ до великого файлу PDF або EPUB із веб-сервера. Що я повинен використовувати директорію кешу або файли? Дякую.
Ishwor Khanal

15

Я найкращий спосіб очистити кеш програми, коли діяльність завершується, щоб кожен раз кеш очищався, коли виклик нової активності.

помістіть цей код в 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();
}

5
Після onDestroy()супервиклику? ти пані?
Yousha Aleayoub

1

Я думаю, що ідея, яка стоїть за кешем, полягає в тому, щоб писати на ньому все, що завгодно, і Android буде керувати своїм розміром, якщо він стане занадто високим.

Слід пам’ятати, що ви можете писати файли в кеш-пам’яті, але завжди перевіряє, чи файл зберігається, намагаючись отримати до нього доступ. І нехай android керує цим кешем.


1

Залежить від типу застосування:

  • Деякі програми використовують лише окремі сеанси, і їм не потрібно запам'ятовувати будь-які дані, тому ви можете очистити кеш, коли хочете (деякі програми навіть роблять це автоматично в своїх операціях 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-сховищі, а ваші налаштування та історію пошуку зберігають у кеші ==> картографічні дані специфічні для програми, налаштування та історія пошуку - для користувача.


0

Згідно з документацією, система очистить кеш, коли на пристрої мало внутрішньої пам’яті . Оскільки API8 у вас є метод getExternalCacheDir (), який я вважаю корисним, оскільки я прочитав, ви можете мати близько 150 МБ даних, але недоліком зовнішнього кешу є те, що вам доведеться самостійно очистити каталог кешу, якщо він стане занадто великим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.