Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.85
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
#1

После вызова notifydataset() items в listview "моргают" - Программирование Android

30.09.2013, 04:11. Просмотров 1668. Ответов 30
Метки нет (Все метки)

столкнулся с такой проблемой, перерыл stackoverflow, ответа не нашел
есть список listview, который показывает картинки, загружая их из сети/кэша.
для него адаптер у которого есть функция getView()
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder vh;
        ImageView imageView;
        Image image = (Image)getItem(i);
        if (view==null)
        {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.item, null);
            vh = new ViewHolder();
            vh.imageView = (ImageView) view.findViewById(R.id.imageView);
            view.setTag(vh);
        }
        vh = (ViewHolder)view.getTag();
        vh.i = i;
        imageView = vh.imageView;
        imageView.getLayoutParams().height = (int)getImageViewHeight(image.getHeight(),image.getWidth(),context.getResources().getDisplayMetrics().widthPixels, context.getResources().getDisplayMetrics().density);
 
        Log.e("SSS",String.valueOf(listView.getFirstVisiblePosition()+" "+i));
        imageView.setImageBitmap(null);
 
        imageLoader.displayImage(items.get(i).getLink(), imageView, options);
 
        return view;
чтобы добиться плавности прокрутки использую ViewHolder. После добавления новых элементов в список, вызываю notifydataset(). Все элементы в списке перерисовываются, соответственно картинки также перезагружаются (если картинка была в памяти, то она быстро перезагружается, но все же заметно, т.е. на долю секунды imageView становится пустым).
Если не использовать ViewHolder, то все нормально. Картинки которые пользователь сейчас видит не обновляются. Но при это производительность немного прокрутки списка падает.

Для загрузки картинок использую Universal Image Loader. Почти уверен что дело не в нем, т.к. пробовал обходиться и без него.
На всякий случай настроки UIL
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
options = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
                .cacheOnDisc(true)     
                .build();
        config = new ImageLoaderConfiguration.Builder(contex
                .tasksProcessingOrder(QueueProcessingType.FIFO) 
                //.denyCacheImageMultipleSizesInMemory()
                .discCacheSize(3 * 1024 * 1024)
                .threadPriority(Thread.NORM_PRIORITY-1)
                .threadPoolSize(3) // default
                .memoryCacheSize(3 * 1024 * 1024)
                .writeDebugLogs()
                .build();
Не знаю куда копать уже даже....
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.09.2013, 04:11     После вызова notifydataset() items в listview "моргают"
Посмотрите здесь:
Android Как определить "переадресованность" входящего вызова
Ссылки (<a href="LINK">XXX</a>) внутри ListView Android
Android При прокрутке listview изображения подгружаются, но происходит "скачок" списка
Android Баг с items при прокручивании ListView
Отключить перескакивание между edittext после нажатия "готово" Android
Как программно убрать клавиатуру после нажатия кнопки "Далее"? Android
"Cannot resolve symbol R" после очистки проекта Android
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
30.09.2013, 05:25     После вызова notifydataset() items в listview "моргают" #2
попробуйте использовать
Java
1
options.resetViewBeforeLoading();
вместо
Java
1
imageView.setImageBitmap(null);
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
30.09.2013, 17:51  [ТС]     После вызова notifydataset() items в listview "моргают" #3
попробовал, эффект тот же, но теперь и другая проблема. imageView у меня у каждого элемента списка имеет разную высоту, которая рассчитывается и устанавливается в getView. если не использовать
Java
1
imageView.setImageBitmap(null);
то высота иногда рассчитывается не правильно если быстро скроллить список.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
30.09.2013, 18:11     После вызова notifydataset() items в listview "моргают" #4
а почему она разная?
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
30.09.2013, 23:20  [ТС]     После вызова notifydataset() items в listview "моргают" #5
Цитата Сообщение от V0v1k Посмотреть сообщение
а почему она разная?
картинки имеют различное разрешение, я подгоняю все картинки по ширине listview. соответственно, если ширина картинки больше/меньше ширины listview,тогда я делю ширину listview на ширину картинки, получаю коэффициент, потом высоту картинки умножаю на этот коэффициент.
вот функция которая это делает

Java
1
2
3
4
5
6
7
public float getImageViewHeight(int imageHeight, int imageWidth, float needWidth, float density)
    {
        int sideMarginImageView = 24;
        int ivHeight = (int) (imageHeight*((needWidth)/imageWidth));
        ivHeight/=density;
        return ivHeight;
    }
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
30.09.2013, 23:34     После вызова notifydataset() items в listview "моргают" #6
вы imageView подгоняете а не картинку, я так понял вы с scaleType'ом запутались....
впервые вижу такое.
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
30.09.2013, 23:47  [ТС]     После вызова notifydataset() items в listview "моргают" #7
Цитата Сообщение от V0v1k Посмотреть сообщение
вы imageView подгоняете а не картинку, я так понял вы с scaleType'ом запутались....
спасибо, кажется в этом проблема. сейчас попробую

Добавлено через 10 минут
спасибо за помощь, V0v1k!
действительно, если задать фиксированный размер imageview, то все работает прекрасно, но мне нужно каким-то образом подгонять размер imageview под картинку. размеры картинок мне известны еще до загрузки. т.е. пользователь должен видеть пустой imageView уже нужного размера, пока картинка грузится.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
30.09.2013, 23:53     После вызова notifydataset() items в listview "моргают" #8
Цитата Сообщение от ta4 Посмотреть сообщение
но мне нужно каким-то образом подгонять размер imageview под картинку.
зачем?

Добавлено через 1 минуту
обычно картинка подгоняется под ImageView
Netscape
371 / 358 / 48
Регистрация: 02.10.2009
Сообщений: 712
Записей в блоге: 4
30.09.2013, 23:55     После вызова notifydataset() items в listview "моргают" #9
Цитата Сообщение от ta4 Посмотреть сообщение
но мне нужно каким-то образом подгонять размер imageview под картинку
Пишите свой imageview, с барышнями и преферансом.
Кликните здесь для просмотра всего текста
Вот так, например, подгоняется высота imageview, ширину уже сами прикрутите.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
 
public class ResizableImageView extends ImageView {
    
    public ResizableImageView(Context context) {
        super(context);
    }
 
    public ResizableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable d = getDrawable();
        if (d != null) {
            // ceil not round - avoid thin vertical gaps along the left/right  edges
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) Math.ceil((float) width
                    * (float) d.getIntrinsicHeight()
                    / (float) d.getIntrinsicWidth());
            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
    
}
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
30.09.2013, 23:59  [ТС]     После вызова notifydataset() items в listview "моргают" #10
Цитата Сообщение от Netscape Посмотреть сообщение
Пишите свой imageview, с барышнями и преферансом.
спасибо, то что нужно
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
01.10.2013, 00:42  [ТС]     После вызова notifydataset() items в listview "моргают" #11
Цитата Сообщение от ta4 Посмотреть сообщение
спасибо, то что нужно
опять же появилась проблема описанная в первом сообщении. При вызове notifyDataSet() у адаптера списка, начинают перезагружаться все imageView. Если не рассчитывать высоту для imageView (установить постоянную, что мне не подходит) или не использовать viewHolder (без него лаги), то все работает нормально.

метод из моего imageView
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable d = getDrawable();
        if (d != null) {
            // ceil not round - avoid thin vertical gaps along the left/right  edges
            float width = MeasureSpec.getSize(widthMeasureSpec);
            float height = (width/wid*hei);//wid и hei ширина картинки, которая будет загружена из сети
            //Log.e("mes", ""+d.getIntrinsicHeight()+"x"+d.getIntrinsicWidth()+"");
            setMeasuredDimension((int)width, (int)height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
Netscape
371 / 358 / 48
Регистрация: 02.10.2009
Сообщений: 712
Записей в блоге: 4
01.10.2013, 00:49     После вызова notifydataset() items в listview "моргают" #12
Цитата Сообщение от ta4 Посмотреть сообщение
При вызове notifyDataSet() у адаптера списка
А зачем его, собственно, вызывать ?
После удачной загрузки изображения UIL вызывает у imageView метод requestLayout(), после чего изображение обновляется.
Цитата Сообщение от ta4 Посмотреть сообщение
imageView.setImageBitmap(null);
это вообще зачем ?

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder vh;
        Image image = (Image)getItem(i);
        if (view==null)
        {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.item, null);
            vh = new ViewHolder();
            vh.imageView = (ImageView) view.findViewById(R.id.imageView);
            view.setTag(vh);
        }
        vh = (ViewHolder)view.getTag();
        vh.i = i;
        imageLoader.displayImage(items.get(i).getLink(), vh.imageView, options);
 
        return view;
}
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
01.10.2013, 00:55  [ТС]     После вызова notifydataset() items в listview "моргают" #13
Цитата Сообщение от Netscape Посмотреть сообщение
А зачем его, собственно, вызывать ?
После удачной загрузки изображения UIL вызывает у imageView метод requestLayout(), после чего изображение обновляется.

это вообще зачем ?

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder vh;
        Image image = (Image)getItem(i);
        if (view==null)
        {
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.item, null);
            vh = new ViewHolder();
            vh.imageView = (ImageView) view.findViewById(R.id.imageView);
            view.setTag(vh);
        }
        vh = (ViewHolder)view.getTag();
        vh.i = i;
        imageLoader.displayImage(items.get(i).getLink(), vh.imageView, options);
 
        return view;
}
notifyDataSet вызываю, т.к. добавляю новые элементы в конец listView

Java
1
imageView.setImageBitmap(null);
в этой строке может быть косяк. Использую, т.к. при прокрутке списка с использование viewHolder переиспользуются элементы списка, которые уже были показаны и если в "старом "элементе уже показывалась какая-то картинка, то она будет показываться и в "новом", поэтому этой строкой очищаю imageView
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
01.10.2013, 00:57     После вызова notifydataset() items в listview "моргают" #14
зачем вообще высоту устанавливать в рантайме?
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
01.10.2013, 01:02  [ТС]     После вызова notifydataset() items в listview "моргают" #15
Цитата Сообщение от V0v1k Посмотреть сообщение
зачем вообще высоту устанавливать в рантайме?
чтобы не было "скачков", когда imageview меньше картинки по высоте. т.е. картинка загрузилась и imageview неожиданно увеличился по высоте. когда список состоит из одних картинок такое поведение напрягает. А если использовать фиксированную высоту, тогда у картинок различная ширина, что смотрится очень некрасиво
к примеру, в приложении kate mobile (в "новости") реализовано так как я пытаюсь сделать, да во многих приложениях так сделано (где изображения в списке различной высоты), но как пока не могу понять..
Netscape
371 / 358 / 48
Регистрация: 02.10.2009
Сообщений: 712
Записей в блоге: 4
01.10.2013, 01:03     После вызова notifydataset() items в listview "моргают" #16
Цитата Сообщение от V0v1k Посмотреть сообщение
зачем вообще высоту устанавливать в рантайме?
что бы "сжать" ImageView до высоты картинки. поскольку ImageView квадратная.
V0v1k
1158 / 982 / 1
Регистрация: 28.06.2012
Сообщений: 3,462
01.10.2013, 01:08     После вызова notifydataset() items в listview "моргают" #17
Цитата Сообщение от ta4 Посмотреть сообщение
А если использовать фиксированную высоту, тогда у картинок различная ширина, что смотрится очень некрасиво
android:scaleType="centerCrop" разве не то же самое дает что вы пытаетесь сделать?
можно просто фон назначить для картинок, будет лучше смотреться.

Добавлено через 1 минуту
Цитата Сообщение от Netscape Посмотреть сообщение
что бы "сжать" ImageView до высоты картинки.
XML
1
android:scaleType="centerInside"
Netscape
371 / 358 / 48
Регистрация: 02.10.2009
Сообщений: 712
Записей в блоге: 4
01.10.2013, 01:09     После вызова notifydataset() items в listview "моргают" #18
Похоже, это баг:
https://github.com/nostra13/Android-...der/issues/395

Попробуйте более старую версию, что ли. А то в последней много изменений, автор мог и накосячить где-то.
ta4
0 / 0 / 0
Регистрация: 09.05.2012
Сообщений: 19
01.10.2013, 01:18  [ТС]     После вызова notifydataset() items в listview "моргают" #19
Цитата Сообщение от Netscape Посмотреть сообщение
Похоже, это баг:
https://github.com/nostra13/Android-...der/issues/395

Попробуйте более старую версию, что ли. А то в последней много изменений, автор мог и накосячить где-то.
Пробовал решение описанное по ссылке, тоже не работало. попробую заменить UIL другой подобной библиотекой для теста (или старую версию uil, как вы советуете).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.10.2013, 01:19     После вызова notifydataset() items в listview "моргают"
Еще ссылки по теме:
Android Метод вызова Activiti через ListView
Android Приложение падает после вызова finish
Пустой список после вызова adapter.notifyDataSetChanged Android
Как изменится стек после вызова активити другого приложения Android
Метод фрагмента onResume() перестает вызываться после вызова метода recreate() для Activity Android

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Netscape
371 / 358 / 48
Регистрация: 02.10.2009
Сообщений: 712
Записей в блоге: 4
01.10.2013, 01:19     После вызова notifydataset() items в listview "моргают" #20
Цитата Сообщение от V0v1k Посмотреть сообщение
android:scaleType="centerInside"
Это не одно и тоже.
Миниатюры
После вызова notifydataset() items в listview "моргают"  
Yandex
Объявления
01.10.2013, 01:19     После вызова notifydataset() items в listview "моргают"
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru