Android кеширование изображений - как? - PullRequest
8 голосов
/ 29 июля 2011

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

Я пробовал два разных подхода:

  1. Сохранить всеизображения в памяти, когда определенный предел начинает превышаться, начинайте их удалять
  2. Пусть Android исправит это с помощью SoftReferences

В 2. это просто очищает их иногда, когда я их выделяю!И я не выделяю слишком много - 30-40 изображений 50х50 пикселей.

Так что я придерживаюсь одного.Вопрос в том, каков предел?

  1. Могу ли я получить от устройства надежную информацию о том, сколько именно растровой памяти у меня осталось?Я провел некоторое исследование, смотрю значения DDMS, он просто занимает все больше места (если я не убираюсь), пока не взорвется.В один момент осталось только 200 КБ, затем система предоставляет еще 2 МБ ...
  2. В настоящее время я использую какое-то эвристическое решение, основанное на модели устройства или размере экрана.Я думаю, что это тупик в долгосрочной перспективе.У некоторых телефонов есть исключения из памяти, на других - совершенно бесплатно.
  3. Есть ли другое, правильное решение?

Ответы [ 5 ]

8 голосов
/ 11 августа 2011

Самый важный вопрос: вы recycle() используете свои растровые изображения? Это очень важно для приложений до Gingerbread (возможно, и после Gingerbread).

Просмотр Управления памятью для приложений Android сеанс из Google I / O 2011 помог мне лучше понять особенности разработки для Android.

В этом видео упоминается инструмент под названием MAT - Memory Analyzer - который полезен для определения наличия утечек в памяти объектов, слоняющихся вокруг. Возможно, у вас больше, чем 30-40, как вы думаете.

Для просмотра и / или регистрации текущего размера кучи и т. Д. Я бы предложил использовать код в этом ответе об исключениях Android Out of Memory .

4 голосов
/ 15 августа 2011

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

Общая идея состояла в том, чтобы добавить изображения в Caching Manager, который а) сохраняет изображение в ассоциативном контейнере (HashMap), используя ключ на основе метаданных, и б) записывает файл изображения на SDCard. ,

При нехватке памяти я выпускаю HashMap. Тем не менее, изображения все еще могут быть извлечены из SD_Card и снова кэшироваться в память.

Я смог сделать это без переработки и до сих пор не вижу проблем с памятью. Насколько я понимаю, переработка не является необходимой, но помогает получить более ранний выпуск памяти, используемой для «растровых изображений», из-за того, что при выделении для растровых изображений в пред-Gingerbread-ОС используется Native Memory. то есть память, которая не является частью кучи Далвика. Таким образом, сборщик мусора не освобождает эту память, а освобождается политиками, специфичными для реализации.

Это из класса Cache_Manager:

public static synchronized void addImage(Bitmap b, String urlString, boolean bSaveToFile, IMAGE_TYPES eIT, boolean bForce)
{
    String szKey = getKeyFromUrlString(urlString, eIT);

    if (false == m_hmCachedImages.containsKey(szKey) || bForce)
    {
        m_hmCachedImages.put(szKey, b);
        if (bSaveToFile)
        {
            boolean bIsNull = false;
            // Write a null object to disk to prevent future query for non-existent image.
            if (null == b)
            {
                try
                {
                    bIsNull = true;
                    b = getNullArt();
                }
                catch (NullPointerException e)
                {
                    e.printStackTrace();
                    throw e;
                }
            }

            // Don't force null art to disk
            if (false == File_Manager.imageExists(szKey) || (bForce && bIsNull == false))
                File_Manager.writeImage(b, szKey);
        }
    }
}

// Вот пример writeImage () из класса File_Manager

public static void writeImage(Bitmap bmp, String szFileName)
{
    checkStorage();

    if (false == mExternalStorageWriteable)
    {
        Log.e("FileMan", "No Writable External Device Available");
        return;
    }

    try
    {
        // Create dirctory if doesn't exist
        String szFilePath = getFilesPath();
        boolean exists = (new File(szFilePath)).exists();
        if (!exists)
        {
            new File(szFilePath).mkdirs();
        }

        // Create file
        File file = new File(szFilePath, szFileName);

        // Write to file
        FileOutputStream os = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.PNG, 90, os);
    } catch (IOException e)
    {
        // Unable to create file, likely because
        // external storage is
        // not currently mounted.
        Log.e("FileMan", "Error writing file", e);
    } catch (Exception e)
    {
        e.printStackTrace();
        throw e;
    }
}
2 голосов
/ 29 июля 2011

Предел связан с размером кучи виртуальной машины на устройстве, на котором он работает, поскольку он отличается от устройства к устройству и от ОС к ОС и может варьироваться от 16 МБ (всего для приложения) до 256 МБ + (для планшетов).

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

Существуют методы дляпроверка количества свободного места в куче и его размера:

Эта ссылка API поможет вам с доступными методами:

http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass

0 голосов
/ 16 августа 2011

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

0 голосов
/ 15 августа 2011

С высокоуровневой точки зрения загрузка и кэширование изображений являются частью GreenDroid Framework .Проверьте это.

...