Существует ли замена для виджета Галерея с утилизацией View? - PullRequest
12 голосов
/ 26 апреля 2011

Виджет Галерея по умолчанию на Android не перерабатывает представления - каждый раз, когда вызывается представление для новой позиции, виджет всегда вызывает метод getView адаптера с convertView, установленным в ноль.

Когда вы прокручиваете назад и вперед, это заканчивается множеством создаваемых представлений, которые, по-видимому, перерабатывает компонент рециркуляции, в котором хранит их Галерея, и приводит к ситуации с OOM.

Вы можете легко проверить это с несколькими изображениями большого размера в качестве элементов вашей галереи, но только TextView вызовет это в конце. Поместите оператор log со счетчиком в метод * getView вашего адаптера и посмотрите, сколько новых представлений создано.

Существует ли сторонний виджет, который ведет себя как галерея, но также реализует переработку вида?

Ответы [ 5 ]

24 голосов
/ 04 мая 2011

Мое решение, в конце концов, заключалось в предложении @ CommonsWare изменить исходный код галереи. Для этого также необходимо скопировать следующие файлы:

  • AdapterView
  • AbsSpinner

но это довольно просто.

После этого я изменил код, сделав следующее:

RecycleBin (AbsSpinner)

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

Gallery

  • Использовал отражение (тьфу), чтобы изменить частную переменную mGroupFlags, равную ViewGroup, чтобы разрешить дочерний переупорядочение - я также установил логическое значение, указывающее, был ли доступ к полю успешным, который я тестировал перед использованием компонента.
  • Удалены все звонки на mRecycler.clear()
  • Количество предметы, которые галерея должна отображать меняется по мере прокрутки и существующего реализация очистит переработчик, когда (а) setSelection был называется (б) произошла прокрутка движения

С этими модификациями мой счетчик в моем методе newView в моем адаптере достиг ... 7.

Вот код (размещен в открытом доступе 2013/08/07 под http://en.wikipedia.org/wiki/WTFPL)

1 голос
/ 26 ноября 2013

На самом деле есть альтернатива, хотя я лично не проверял ее:

https://github.com/falnatsheh/EcoGallery

0 голосов
/ 14 января 2014

Очень поздно на вечеринку, но я изменил EcoGallery, чтобы сделать еще несколько вещей (и избежать некоторых сбоев).

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

Чтобы продемонстрировать это, в примере используются Picasso и PullToRefresh.

Оригинальный код, авторские права и т.п. принадлежат Google, поэтому вините их за создание такого дерьмового виджета.

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

Google понял это и осудил это.Используйте ViewPager или HorizontalScrollList и справьтесь с ограничениями каждого из них.

Если вы все еще хотите пойти дальше и использовать эту «галерею», не стесняйтесь, она работает, но она может привести к сбою вашего приложения и может расстроить вас.

0 голосов
/ 03 мая 2012

Я использовал патч от http://code.google.com/p/android/issues/detail?id=3376#c19

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

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

что-то ещекак это:

private static Bitmap decodeFile(File f, int size, int suggestedScale) {

    int scale = 1;
    Bitmap bmp = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;

        if(suggestedScale > 0)
            scale = suggestedScale;
        else {
            if (width_tmp >= height_tmp) {
                scale = Math.round((float)(width_tmp) / size);
            } else {
                scale = Math.round((float)(height_tmp) / size);
            }
        }

        if(scale < 2)
            return BitmapFactory.decodeFile(f.getPath()); 

        Debug.i(TAG, "width: " + width_tmp + "  height: " + height_tmp + "  scale: " + scale);


        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {

    } catch(OutOfMemoryError e) {
        Debug.i(TAG, "we retry it cause of an OutOfMemoryException");
        return decodeFile(f, size, scale+1);
    } catch(Exception e){
        Debug.w(TAG, e);
    }
    return bmp;
}

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

...