Кэширование изображений Android-как?

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

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

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

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

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

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

5 ответов


самый важный вопрос:recycle()-ing ваши растровые изображения? Это очень важно для pre-Gingerbread применений (возможно столб-Gingerbread слишком).

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

в этом видео упоминается инструмент под названием мат - a Анализатор Памяти - это полезно для определения, есть ли у вас объекты, висящие в памяти, которые были просочились. Возможно, у вас более 30-40 вы думаете, что у вас есть.

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


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

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

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

я смог сделать это без переработки и до сих пор не вижу проблем с памятью. Как я понимаю, утилизация не нужна, но помогает получить более ранний выпуск памяти, используемой для" растровых изображений", из-за того, что выделение для растровых изображений в пре-пряничных Осах использует родную память. то есть память, которая не является частью кучи Dalvik. Так что сборщик мусора не бесплатно эта память, скорее, освобождается путем реализации определенных политик.

это из класса 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;
    }
}

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

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

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

этот API ref поможет вам с доступными методами:

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


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


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