Чистка Галерея в призыве Активность для Сота, чтобы избежать OOME? - PullRequest
0 голосов
/ 10 мая 2011

Я создаю средство просмотра книг для Android 3.0 Honeycomb. Он отлично работает на Samsung Galaxy Tab, но получает множество ошибок OutOfMemory на Motorola Xoom на 3.0.1. Оба устройства имеют пространство кучи виртуальной машины 48 МБ.

У меня есть 2 занятия:

BookActivity - имеет SlowGallery, который загружает изображения 1280x640, и небольшую галерею, которая загружает изображения 160x80.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '' * '* * * * * * *' '*' * * * * * * * * * * «Мозг» - это незначительное переопределение.

BitmapActivity - имеет один ImageView, который загружает изображение 4488x2244, и небольшую галерею, которая загружает изображения 160x80. Уменьшение размера изображения не вариант, поскольку пользователь намерен увеличить изображение до 100%.

Я поместил это в метод загрузки растровых изображений, чтобы уменьшить растровое изображение до 16-разрядных:

BitmapFactory.Options o2 = new BitmapFactory.Options();
if (compressColor) o2.inPreferredConfig = Bitmap.Config.RGB_565;
o2.inPurgeable = true;
o2.inInputShareable = true;
o2.inSampleSize = (int) scale;
b = BitmapFactory.decodeStream(fis, null, o2);

Когда я дважды щелкаю по галерее BookActivity, она вызывает BitmapActivity, передавая соответствующий номер изображения, который нужно открыть. Я могу сделать это 1-3 раза, введя BitmapActivity, затем щелкнув Назад, прежде чем он попадет в OutOfMemoryError.

При двойном прикосновении к Галерее вызывается PageAdapter.purge (), который, по-видимому, визуально выгружает изображения галереи.

Это BookActivity.PageAdapter, который является адаптером для SlowGallery:

private class PageAdapter extends BaseAdapter {
private final LayoutInflater mInflater;
private Page currentPage;
private boolean purge = false;
private WeakReference<Bitmap> weakReferenceBitmap;
public PageAdapter(Context context) {
    mInflater = LayoutInflater.from(context);
}
public void unpurge() {
    purge = false;
    notifyDataSetChanged();
}   
public void purge() {
    purge = true;
    holder = null;
    notifyDataSetChanged();
}       
@Override
public int getCount() {
    if (listPages==null || purge) return 0;
    return listPages.size();
}
@Override
public Object getItem(int position) {
    return null;
}
@Override
public long getItemId(int position) {
    return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.gallery_pages, null);
        holder = new ViewHolderIssues();
        holder.image = (ImageView) convertView.findViewById(R.id.ImageViewPage);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolderIssues) convertView.getTag();
    }
    if (position < listPages.size()) {
        currentPage = listPages.get(position);
        File f = new File(Engine.PATH + currentPage.getImageMedium());
        if (!purge) {
            if (!f.exists()) {
                holder.image.setImageResource(R.drawable.loading);
                Engine.triggerTrickle(currentPage.getImageMedium(), WeightedAsset.IMAGE_MEDIUM, getApplicationContext());                   
            } else {
                weakReferenceBitmap = new WeakReference<Bitmap>(Engine.loadImageFromBitmap(currentPage.getImageMedium(), screenWidth, 1, true));
                if (weakReferenceBitmap.get()!=null) {
                    holder.image.setImageBitmap(weakReferenceBitmap.get());
                } else {
                    holder.image.setImageDrawable(null);
                }
            }
        } else {
            weakReferenceBitmap.clear();
            holder.image.setImageDrawable(null);
            holder = null;
            System.gc();
        }
        f = null;
    }
    return convertView;
}
}

Глядя на файл HPROF, под деревом доминатора, кажется, что BookActivity.SlowGallery все еще существует, даже когда я нахожусь в BitmapActivity. Когда в BookActivity, SlowGallery занимает 3,2-6,5 МБ (1,6 МБ на изображение), но в BitmapActivity это занимает 1,6 МБ (SlowGallery.LinearLayout.ImageView.BitmapDrawable = 1,6 МБ). Как мне избавиться от SlowGallery?

Ответы [ 2 ]

0 голосов
/ 23 мая 2011

Спасибо! Мне удалось изменить его, чтобы переработать растровое изображение. Тем не менее, галерея все еще не работала, потому что BitmapActivity.onCreate вызывается раньше BookActivity.onDestroy. Если бы я действительно вызвал функцию purge (), мне бы удалось очистить большую ее часть, за исключением просмотра с щелчком / выбранным (поддерживается живым Gallery слушателем двойного касания!)

Затем я уничтожил проклятую галерею и поместил свои ImageView imageviewCurrentPageImageView imageviewFlipperPage) и анимировал их. ImageviewFlipperPage будет немедленно уничтожен, когда анимация будет завершена, поэтому я гарантированно загрузлю максимум 2 растровых изображения. Gallery может принимать до ПЯТЬ видов с выбранными, выбранными видами и т. Д.

Я также добавил это для дальнейшей изоляции использования памяти:

<activity android:name=".BitmapActivity" android:process=":BitmapActivity" ...>

Однако возникла сложность, заключающаяся в том, что статические классы не являются общими для процессов. Следовательно, если бы в BookActivity я сделал Engine.SESSION_ID = 5, где SESSION_ID является статическим, я бы не смог прочитать его в BitmapActivity's Engine.SESSION_ID.

0 голосов
/ 10 мая 2011

Ах, там довольно сложный кусок кода.Слабые ссылки могут помочь, но в целом, если использовать ImageView в адаптере, прежде чем устанавливать новое растровое изображение, вы должны извлечь старое растровое изображение и затем вызвать Bitmap.recycle().Вы должны также сделать это своей BitmapActivity, когда оно destroy ed.Это должно делать большую часть того, что вам нужно.

...