Подтвердить что ты не робот

Еще один getView вызвал несколько раз

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

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

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

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

Но когда я удаляю setImageBitmap из AsyncTask, все это не произойдет!

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

Вот код:

<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);

Дополнительная информация:

При создании нового представления указатель stacktrace, показанный getView, вызывается из ListView.makeAndAddView() Но в бесполезной полосе getViews она исходит от ListView.measureHeigthOfChildren()

Итак, кажется, что макет изменяется, когда я устанавливаю битмап...

4b9b3361

Ответ 1

Проблема была в макете ListView.

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

Ответ 2

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

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

Ответ 3

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

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

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

Несколько полезных ссылок:

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

Ленивая загрузка изображений в ListView

Ответ 4

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

Ответ 5

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

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
         if (convertView != null)
            return convertView;
         else {
            //your code...
         }
    }