2012-06-25 4 views
19

Каждый элемент в моем ListView содержит ImageView и TextView, он будет заполнен удаленной информацией.Еще один getView называется несколько раз

У меня есть URL-адрес для ImageView, поэтому я запускаю AsyncTask, который загружает изображение и будет вызывать setImageBitmap с загруженным растровым изображением.

Это очень хорошо, но когда создается ListView, часто вызывается getView(). Он вызывает около 7 раз getView для первых 10 строк (всего 7 видимых). (So: 0, 1 и т. Д., 10, 0, 1 и т. Д.).

Тогда я могу просто плавно прокрутить до 10-го пункта. Но после этого для каждой новой строки listview снова вызывает примерно 7 раз getView для первых 10 элементов. (Это приведет к задержке ..)

Но когда я удаляю setImageBitmap с AsyncTask, этого все не будет!

В чем может быть проблема? Может ли быть, что какой-то макет будет большим, что вызовет еще одну полосу getView?

Вот некоторые код:

<ListView 
    android:id="@+id/mylist" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:layout_alignParentBottom="true" 
    android:layout_below="@+id/mydivider" 
    android:divider="@+color/mycolor" 
    android:dividerHeight="2dp" 
    android:fadingEdge="none" 
    android:fastScrollEnabled="true" 
    android:listSelector="@android:color/transparent" 
    android:scrollbars="horizontal" 
    android:scrollingCache="false" 
    android:smoothScrollbar="false" /> 

AsyncTask:

public static class MyTask extends AsyncTask<String, Integer, Bitmap> { 
    private LruCache<String, Bitmap> mMap; 
    private String mUri; 
    private int mPosition; 
    private ViewHolder mHolder; 

    public MyTask (ViewHolder holder, int position, LruCache<String, Bitmap> map) { 
     mMap = map; 
     mHolder = holder; 
     mPosition = position; 
    } 

    @Override 
    protected Bitmap doInBackground(String... url) { 
     mUri = url[0]; 
     return getBitmapFromURL(mUri); 
    } 

    @Override 
    protected void onPostExecute(Bitmap b) { 
     if (b != null) { 
      mMap.put(mUri, b); 
      if (mPosition == mHolder.position) { 
       holder.image.setImageBitmap(b); 
      } 
     } 
    }; 
} 

GetView()

row = convertView; 
ViewHolder holder; 
if (row == null) { 
    row = vi.inflate(R.layout.mylayout, null); 
    holder = new ViewHolder(); 
    holder.image = (ImageView) row.findViewById(R.id.myimage); 
    holder.title = (TextView) row.findViewById(R.id.mytext); 
    row.setTag(holder); 
} else { 
    holder = (ViewHolder) row.getTag(); 
} 

holder.title.setText("text"); 
holder.image.setImageResource(R.drawable.mydefaulticon); 
holder.position = position; 
startMyTask(content, holder, position); 

Некоторые больше информации:

Когда новый вид создается showtrace show п GetView был вызван из ListView.makeAndAddView() Но в бесполезную полосу getViews он исходит из ListView.measureHeigthOfChildren()

Так что, похоже, как раскладка меняется, когда я установил Bitmap ...

+0

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

ответ

32

Проблема заключалась в Макет ListView.

Параметр layout_width был установлен wrap_content, когда я изменил его на fill_parent проблема исчезла ...

+2

Спасибо за это. Работал 100%. – Ron

+0

Также работал для меня. Интересно, связано ли это с ограниченным размером списка listView, если он соответствует его родительскому элементу, а не заполняет его? Более крупный listView будет логически вызывать getView() чаще, поскольку доступно больше отдельных элементов. –

+1

В моем случае getView вызывается для одной позиции неоднократно и бесконечно, хотя эта конкретная позиция не была чем-то особенным. У меня было несколько типов просмотра, похожих на тот же экран, а также на другой вид. Проблема заключалась в том, что у меня было несколько элементов в макете, и один из элементов имел ширину, определенную layoutWeight = "1", чтобы получить оставшееся пространство после других виджетов. Перестановка этого на фиксированную ширину решила проблему. – velis

3

я рекомендую вам смотреть этот видео http://www.youtube.com/watch?v=wDBM6wVEO70

основном андроид будет вызывать GetView несколько раз за это вычисление высоты просмотра и прочее, так что вам нужно реализовать какой-то кэш в вашем асинхронном, проверьте http://code.google.com/p/android-query/, который имеет, что если вы не использовать проверку подлинности

2

Проблема заключается в том, что ваш ListView не знает, что из каждого элемента. При инициализации ListView будет измерять всех своих детей и использовать эту информацию. Что вы делаете с вашей AsyncTask, меняете размеры элементов в списке и не позволяете ListView полностью вычеркнуть. Это приведет к тому, что ListView будет вести себя странно.

Решение: вы должны обновить свой ListView, уведомив адаптер, используя notifyDataSetChanged() в PostExecute вашей AsyncTask. Это позволит ListView рисовать себя с новой информацией.

Надеюсь, это сработает!

Несколько ПОЛЕЗНЫЕ ссылки:

http://thinkandroid.wordpress.com/2012/06/13/lazy-loading-images-from-urls-to-listviews/

Lazy load of images in ListView

+0

Посмотрите на эту ссылку: http://stackoverflow.com/a/5092426/929075 notifyDataSetChanged не поможет, когда я хочу обновить только представление. Я не изменяю ArrayList –

0

Извините за поздний ответ. Я столкнулся с той же проблемой в моем адаптере для виджета галереи. Я использовал Universal Image Loader. Решение Martijn's работало для меня. Все, что мне нужно было сделать, - добавить notifyDataSetChanged(), когда изображение было полностью загружено и установлено изображениеViewView.

0

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

 @Override 
     public View getView(final int position, View convertView, ViewGroup parent) { 
     if (convertView != null) 
      return convertView; 
     else { 
      //your code... 
     } 
    } 
Смежные вопросы