Когда очистить кэш dir в Android? - PullRequest
74 голосов
/ 30 марта 2012

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

Вы должны всегда поддерживать файлы кэша самостоятельно и оставаться в пределах разумный лимит занимаемого пространства, например 1 МБ. Когда пользователь удаляет ваше приложение, эти файлы удаляются.

Итак, я взглянул на приложение Currents (Galaxy Nexus) и размер кеша для приложения составляет 110 МБ. Но что странно, так это то, что приложения, такие как Google Currents и Google Maps, кэшируют контент в нечто, называемое (USB Storage Data):

enter image description here

Итак, что это за «Данные USB-накопителя», которые использует предыдущее приложение. И если вы реализуете кеширование в своем приложении, вы зацикливаетесь на всех файлах вашего приложения в кеше , чтобы получать размер каждый раз, когда вам нужно что-то вставить, а затем сравнивать и очищать его? Или вы продолжаете кэшировать содержимое до тех пор, пока Android не решит очистить каталог кэша приложения?

Мне действительно интересно узнать, как протекает управление кешем в Android или, по крайней мере, что другие приложения делают с большим контентом для кеширования.

Ответы [ 5 ]

188 голосов
/ 09 апреля 2012

Прежде чем перейти к вашему вопросу, вот краткое объяснение двух типов хранения:

Cache

Это каталог для приложения в файловой системе. Назначение этого каталога - хранить временные данные, которые могут понадобиться вашему приложению между сеансами, но, возможно, не жизненно важно хранить их вечно. Обычно вы обращаетесь к этому каталогу с помощью Context.getCacheDir(). Это будет отображаться как «Кэш» в настройках вашего приложения.

Файлы

Как и каталог кеша, в вашем приложении также есть специальный каталог для хранения файлов. Файлы в этом каталоге будут существовать до тех пор, пока приложение явно не удалит их или приложение не будет удалено. Обычно вы обращаетесь к этому каталогу с помощью Context.getFilesDir(). Это может отображаться как различные вещи на экране информации о приложении, но на скриншоте это «Данные USB-накопителя».

ПРИМЕЧАНИЕ: Если вы хотите явно разместить на внешнем носителе (обычно на SD-карте), вы можете использовать Context.getExternalFilesDir(String type).

Разница

Обе директории относятся только к вашему приложению (другие приложения не имеют доступа). Одно из различий между каталогом кеша и файлами заключается в том, что если системе не хватает памяти, первое место, куда она собирается освободить ресурсы, - это каталог кеша. Система не удалит данные из каталога файлов. Другое отличие состоит в том, что каталог кэша обычно можно очистить вручную с экрана информации о приложении. Каталог файлов, как правило, тоже может, но очистка каталога файлов также очистит каталог кэша.

Какой из них я использую?

Это зависит от того, насколько важны эти данные по сравнению с временем жизни вашего приложения. Если вам нужны данные только для одного сеанса и вы сомневаетесь, что вам когда-нибудь понадобится использовать эти данные снова, не используйте их. Просто держите это в памяти, пока вам это не понадобится. Если вы подозреваете, что вам нужно повторно использовать данные между несколькими сеансами, но у вас нет , чтобы хранить печатную копию, используйте каталог кеша. Если вам нужны эти данные, независимо от того, что это, или если это достаточно большие данные, которые требуют постоянного хранения, используйте каталог files. Вот несколько примеров, которые я могу вспомнить:

  • Кэш - недавно открытое письмо
    • После открытия кэшируйте данные, чтобы, когда пользователь захочет снова прочитать это электронное письмо, он мгновенно загружался, а снова использовал сеть для извлечения тех же данных. Мне не нужно хранить это вечно, потому что в конечном итоге пользователь получит электронное письмо.
  • Файлы - вложение, загруженное из электронного письма.
    • Это действие пользователя, который говорит: «Я хочу сохранить эти данные, чтобы я мог восстановить их, когда мне это понадобится». Поэтому поместите его в каталог 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;
    }
}

Конечно, это может быть дорогостоящей операцией, поэтому вы должны планировать кэширование в фоновом потоке.

Кроме того, это может быть настолько сложно, насколько вам нужно. В моем примере я предполагаю, что все кэшированные файлы размещены в корне каталога кеша, поэтому я не проверяю потенциальные подкаталоги. Процедура удаления файлов также может стать более сложной, например, удаление файлов по самой старой дате доступа.

При принятии решения о кэшировании данных следует иметь в виду, что вам всегда нужно планировать случай, когда ваши кэшированные данные больше не существуют. Всегда имейте подпрограмму для извлечения данных внешними средствами, когда ваш кеш не имеет их в хранилище. Кроме того, всегда проверяйте свой кэш, прежде чем извлекать данные извне. Цель кэша - сократить сетевую активность, длительные процессы и предоставить отзывчивый пользовательский интерфейс в вашем приложении. Так что используйте его ответственно:)

15 голосов
/ 12 мая 2012

Это лучший способ очистить кэш приложения после завершения действия, чтобы каждый раз очищать кэш при вызове нового действия.

поместить этот код в 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();
}
1 голос
/ 02 апреля 2012

Зависит от типа приложения:

  • Некоторые приложения используют только отдельные сеансы и не нуждаются в запоминании каких-либо данных, поэтому вы можете очистить кеш, когда захотите (некоторые приложения даже делают это автоматически в своей активности 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-хранилище и сохраняют ваши настройки и историю поиска в кэше ==> данные карт относятся к конкретному приложению, настройки и история поиска зависят от пользователя

1 голос
/ 02 апреля 2012

Я думаю, что идея кеша заключается в том, чтобы записать на него все, что вы хотите, и Android будет управлять его размером, если он станет слишком большим.но всегда проверяет, сохранен ли файл при попытке доступа к нему.И пусть андроид управляет кешем.

0 голосов
/ 06 апреля 2012

В соответствии с документацией система очистит кэш, когда на устройстве недостаточно внутренней памяти .Начиная с API8 у вас есть метод getExternalCacheDir () , который я считаю полезным, так как я прочитал, что у вас может быть около 150 МБ данных, но недостатком внешнего кэша является то, что вам придется самостоятельно очищать каталог кэша, если он слишкомбольшой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...