Когда очистить кэш dir в Android?


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

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

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

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

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

5 73

5 ответов:

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

кэш

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

файлы

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

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

Разница

оба каталога предназначены только для вашего приложения (другие приложения не имеют доступа). Одно из различий между каталогом cache и 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;
    }
}

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

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

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

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

поместите этот код в 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();
}

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

вы должны иметь в виду, что вы можете записывать файлы в кэше, но всегда проверяет, если файл сохраняется при попытке доступа к нему. И пусть android управляет Th cache.

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

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

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