Android "Попытка использовать переработанное растровое изображение" ошибка? - PullRequest
19 голосов
/ 13 июня 2010

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

Моя проблема: при использовании опции обновления старые изображения все еще оставались в памяти, и я быстро получил бы OutOfMemoryErrors. Таким образом, если изображения обновляются, я прошёл их через массив и переработал старые изображения. Однако, когда приложение загружает новые изображения в массив, оно завершается с ошибкой «Попытка использовать переработанное растровое изображение».

Насколько я понимаю, переработка растрового изображения уничтожает растровое изображение и освобождает его память для других объектов. Если я хочу использовать растровое изображение снова, оно должно быть повторно инициализировано. Я считаю, что я делаю это, когда новые файлы загружаются в массив, но что-то все еще не так. Любая помощь очень ценится, так как это очень расстраивает. Код проблемы ниже. Спасибо!

public void fillUI(final int refresh) { 
// Recycle the images to avoid memory leaks
if(refresh==1) {
    for(int x=0; x<images.size(); x++)
        images.get(x).recycle();
    images.clear();
    selImage=-1; // Reset the selected image variable
}
final ProgressDialog progressDialog = ProgressDialog.show(this, null, this.getString(R.string.loadingImages));
// Create the array with the image bitmaps in it
new Thread(new Runnable() {
    public void run() {
        Looper.prepare();
        File[] fileList = new File("/data/data/[package name]/files/").listFiles();
        if(fileList!=null) {
            for(int x=0; x<fileList.length; x++) {
                try {
                    images.add(BitmapFactory.decodeFile("/data/data/[package name]/files/" + fileList[x].getName()));
                } catch (OutOfMemoryError ome) {
                    Log.i(LOG_FILE, "out of memory again :(");
                }
            }
            Collections.reverse(images);
        }
        fillUiHandler.sendEmptyMessage(0);
    }
}).start();

fillUiHandler = new Handler() {
    public void handleMessage(Message msg) {
        progressDialog.dismiss();
    }
};

}

Ответы [ 2 ]

19 голосов
/ 13 июня 2010

Вам на самом деле не нужно вызывать метод recycle здесь.Кнопка Обновить должна просто очистить массив, сборщик мусора освободит память позже.Если вы получаете OutOfMemory, это означает, что некоторые другие объекты все еще ссылаются на ваши старые изображения, и сборщик мусора не может их удалить.

Я могу предположить, что некоторые ImageViews отображают ваши растровые изображения и сохраняют ссылки на эти растровые изображения.Вы не можете удалить старые растровые изображения, пока они все еще отображаются.Поэтому возможное решение - очистить ImageVIews тоже.После этого вы можете очистить массив и заполнить его новыми изображениями.

Recycle освобождает память, но некоторые ImageView по-прежнему отображают растровое изображение и не могут этого сделать после перезагрузки, поэтому вы получаете «Попытка использоватьпереработанное растровое изображение ".

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

4 голосов
/ 03 сентября 2010

Если объем памяти очень велик, вам лучше перезапустить растровое изображение самостоятельно. GC не может контролироваться.

...