Галерея ImageAdapter convertView всегда пуста

Я использую Галерея с 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 ответа

Решение

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

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

[V1, V2, V3]

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

[V2, V3, V1]

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

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

У меня нет опыта работы с виджетом Галерея, но я часто использую 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>

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

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

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

Другие вопросы по тегам