Галерея ImageAdapter convertView всегда пуста - PullRequest
14 голосов
/ 11 октября 2011

Я использую Галерею с ImageAdapter, чтобы загрузить его с ImageViews, которые извлекают изображения из моих ресурсов.Моя проблема в том, что convertView, который передается методу getView () в моем адаптере, всегда имеет значение null.Это означает, что новый ImageView создается каждый раз, когда вызывается getView ().Это приводит к ужасному предварительному исполнению, потому что GC постоянно работает, чтобы стереть все эти созданные и более не используемые ImageView.

Это, очевидно, известная ошибка: Кэш представления галереи не работает;никогда не преобразует представления. .

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

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

Я нашел код для виджета «Галерея» здесь: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/widget/Gallery.java

Я не до конца понимаю, но вижу, что он вызывает

child = mAdapter.getView(position, null, this);

в строке 745. Мое (снятое в темноте) догадывается, что это корень проблемы.

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

РЕДАКТИРОВАТЬ: Лучшим решением, которое я когда-либо нашел, была реализация под названием EcoGallery.Единственное место, где я могу найти ссылку на него онлайн, это .Чтобы это работало, вы должны поместить каждый кусок в нужное место в вашем проекте.

Ответы [ 3 ]

3 голосов
/ 02 июня 2012

Нет особого опыта с этой ошибкой, но я ранее занимался пользовательским кэшированием с помощью стороннего пейджера (до поддержки lib).

Честно говоря, это не так уж сложно. В моем случае я знал, что на экране будет максимум один элемент. Но я также хотел, чтобы элемент слева и справа был предварительно загружен (это были веб-просмотры, извлекающие данные из сети). Итак, у меня есть простой массив из 3 представлений.

[V1, V2, V3]

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

[V2, V3, V1]

Было просто не отставать. Или вы можете просто сделать математику и рассчитать позицию относительно относительной позиции кэша.

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

1 голос
/ 02 июня 2012

У меня нет опыта работы с виджетом Галерея, но я часто использую ListView с изображениями. В соответствии с вашей проблемой и ссылкой на проблему Google они до сих пор не решили эту проблему.

Итак, есть решение с хорошей библиотекой (и примерами внутри нее), которая решает проблемы с кешем / ajax и многое другое.

Ссылка на библиотеку

или, более конкретно, ссылка на изображение примеры

Если вы скачаете их примеры, вы увидите, как они реализовали галерею с помощью виджета Галерея, используя свой служебный класс AQuery в

com.androidquery.test.image.ImageLoadingGalleryActivity класс.

Фрагмент из кода:

    final List<Photo> entries;// here only to show what enteries are...

    listAq = new AQuery(this); //define as Action class member, here only to show what it is

    ArrayAdapter<Photo> aa = new ArrayAdapter<Photo>(this, R.layout.gallery_item, entries){

        public View getView(int position, View convertView, ViewGroup parent) {

            if(convertView == null){
                convertView = getLayoutInflater().inflate(R.layout.gallery_item, parent, false);
            }

            Photo photo = getItem(position);

            AQuery aq = listAq.recycle(convertView);

            aq.id(R.id.name).text(photo.title);

            String tbUrl = photo.tb;

            if(!aq.shouldDelay(position, convertView, parent, tbUrl)){
                aq.id(R.id.tb).image(tbUrl);
                aq.id(R.id.text).text(photo.title).gone();
            }else{
                aq.id(R.id.tb).clear();
                aq.id(R.id.text).text(photo.title).visible();
            }


            return convertView;

        }


    };

    aq.id(R.id.gallery).adapter(aa);

Где Photo - это просто объект POJO (получен с удаленного устройства):

class Photo {
    String tb;
    String url;
    String title;
    String author;
}

R.id.gallery относится к

 <Gallery
        android:id="@+id/gallery"
        android:layout_width="fill_parent"
        android:layout_height="200dip" />

И R.layout.gallery_item относится к:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="100dip"
        android:layout_height="75dip" >

        <ProgressBar
            android:id="@+id/progress"
            android:layout_width="15dip"
            android:layout_height="15dip"
            android:layout_centerInParent="true" />

        <ImageView
            android:id="@+id/tb"
            style="@style/GalleryItem"
            android:layout_width="100dip"
            android:layout_height="75dip" />

        <TextView
            android:id="@+id/text"
            android:layout_width="100dip"
            android:layout_height="75dip"
            android:gravity="center"
            android:maxLines="4"
            android:padding="15dip"
            android:text="Dummy TextDummy TextDummy TextDummy TextDummy Text"
            android:textColor="#FFFFFFFF"
            android:textSize="8sp" />

    </RelativeLayout>

Надеюсь, вы найдете эту библиотеку полезной для решения вашей проблемы.

0 голосов
/ 07 июня 2012

Я справился с этим, используя собственный кеш, как подсказывает dskinner.

Я предварительно рассчитываю (ширина экрана / минимальная ширина элемента) максимальное количество элементов, которые можно показать в галерее на экране за один раз, и добавляю еще несколько (галерее потребуются дополнительные элементы для отображениявлево и вправо при прокрутке через него).Я создаю массив такого размера - представления создаются по запросу и помещаются в кеш.Используйте position% cachesize, чтобы выяснить, какое кэшированное представление будет возвращено при вызове getView.

...