Изменение изображения при прокрутке сетки

GridView загружает изображения по URL-адресу. Когда я прокручиваю gridview, больше шансов на изображение, как это исправить... Я пробовал imageAdapter.notifyDataSetChanged(), gridView.invalidateViews().. Я не нашел решения этой проблемы.

public class ImageAdapter extends BaseAdapter{

    private Context mContext;
    private LayoutInflater mInflater;   
    private ArrayList<NodeFood> listImage = new ArrayList<NodeFood>();

    public ImageAdapter(Context c, ArrayList<NodeFood> listImage){
        this.mContext = c;
        this.listImage = listImage;
    }

    public class ViewHolder{
        ImageView imageView;
        ProgressBar progress;
    }

    public int getCount() {
        return listImage.size();
    }

    public Object getItem(int arg0) {
        return arg0;
    }

    public long getItemId(int arg0) {
        return arg0;
    }

    public View getView(int arg0, View arg1, ViewGroup arg2) {
        final ViewHolder holder;
        if(arg1 == null){
            holder  = new ViewHolder();
            mInflater = LayoutInflater.from(mContext);
            arg1    =   mInflater.inflate(R.layout.layout_item_grid, null);
            holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
            holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
            holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
            arg1.setTag(holder);
        }else{
            holder = (ViewHolder)arg1.getTag();
        }
        holder.imageView.setTag(arg0);
        holder.progress.setTag(arg0);
        NodeFood a = this.listImage.get(arg0);
        String URL = a.getSRC();
        task_LoadIMG bb = new task_LoadIMG(URL,holder);
        bb.execute();
        return arg1;
    }   

    public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
        private String url;
        private ViewHolder holder;
        public task_LoadIMG(String url, ViewHolder holder){
            this.url = url;
            this.holder = holder;
        }
        @Override
        protected Bitmap doInBackground(Void... arg0) {
            try{
                URL aURL = new URL(this.url);
                URLConnection connect = aURL.openConnection();
                connect.connect();

                InputStream is = connect.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                Bitmap bm = BitmapFactory.decodeStream(bis);
                bis.close();
                is.close();
                return bm;
            }catch(IOException e){
                return null;
            }
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            holder.progress.setVisibility(View.GONE);
            holder.imageView.setImageBitmap(result);
            holder.imageView.setScaleType(ScaleType.CENTER_CROP);
        }
    }
}

person bulubuloa    schedule 05.08.2012    source источник
comment
Я столкнулся с той же проблемой с просмотром списка, когда я прокручивал список вниз, а затем прокручивал вверх, изображения менялись случайным образом. Затем я использовал ЭТОТ КОД ДЛЯ ЗАГРУЗКИ ИЗОБРАЖЕНИЙ, просто попытайся. Может быть полезно для вас.   -  person Chintan Raghwani    schedule 05.08.2012


Ответы (3)


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

Чтобы обойти это, сохраните URL-адрес изображения ячейки в свойстве tag ячейки. Затем убедитесь, что URL-адрес ячейки тот же, когда AsyncTask завершится. Если это не то же самое, то ячейка уже была переработана, и вам следует отказаться от обновления. Вот код:

public View getView(int arg0, View arg1, ViewGroup arg2) {
    final ViewHolder holder;
    if(arg1 == null){
        holder  = new ViewHolder();
        mInflater = LayoutInflater.from(mContext);
        arg1    =   mInflater.inflate(R.layout.layout_item_grid, null);
        holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
        holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
        holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
        arg1.setTag(holder);
    }else{
        holder = (ViewHolder)arg1.getTag();
    }
    NodeFood a = this.listImage.get(arg0);
    String URL = a.getSRC();
    holder.imageView.setTag(URL);
    task_LoadIMG bb = new task_LoadIMG(URL,holder);
    bb.execute();
    return arg1;
}   

public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
    private String url;
    private ViewHolder holder;
    public task_LoadIMG(String url, ViewHolder holder){
        this.url = url;
        this.holder = holder;
    }
    @Override
    protected Bitmap doInBackground(Void... arg0) {
        try{
            URL aURL = new URL(this.url);
            URLConnection connect = aURL.openConnection();
            connect.connect();

            InputStream is = connect.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            Bitmap bm = BitmapFactory.decodeStream(bis);
            bis.close();
            is.close();
            return bm;
        }catch(IOException e){
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        if (url.equals(holder.imageView.getTag()) {
            holder.progress.setVisibility(View.GONE);
            holder.imageView.setImageBitmap(result);
            holder.imageView.setScaleType(ScaleType.CENTER_CROP);
        } else {
            // View was updated in the meantime, ignore the image
        }
    }
}

Вы также можете рассмотреть возможность отмены AsyncTask, как только ячейка будет перезапущена, чтобы сэкономить пропускную способность / циклы ЦП. Это остается в качестве упражнения для читателя.

person Edward Dale    schedule 05.08.2012

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

повторите свой ImageView с помощью com.android.volley.toolbox.NetworkImageView

что-то типа:

<com.android.volley.toolbox.NetworkImageView
android:id="@+id/twitter_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"/>


private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;

private LruCache<String, Bitmap> mMemoryCache;

тогда:

final int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;
    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {

        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }

    };

    mRequestQueue = Volley.newRequestQueue(context);
    mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {

        public void putBitmap(String url, Bitmap bitmap) {
            mMemoryCache.put(url, bitmap);
        }

        public Bitmap getBitmap(String url) {
            return mMemoryCache.get(url);
        }
    });

Используйте залп:

NetworkImageView image = (NetworkImageView) row.findViewById(R.id.ivGridViewImage);

image.setImageUrl(url, mImageLoader);
person SpyZip    schedule 21.02.2014
comment
Обратите внимание, что ответы только по ссылкам не рекомендуются, ответы SO должны быть конечной точкой поиска. для решения (по сравнению с еще одной остановкой ссылок, которые со временем устаревают). Пожалуйста, рассмотрите возможность добавления здесь отдельного синопсиса, оставив ссылку в качестве ссылки. - person kleopatra; 21.02.2014

У меня была такая же проблема с моим GridView. Хотя элементов не так много, всего 24, и я загрузил изображения с SD-карты своего телефона, а не из Интернета, я все еще получал изображения, прыгающие со всех сторон, когда я прокручивал, что на самом деле было всего лишь одна или две строки, которые были скрыты от просмотра в время.

Что я сделал, так это просто добавил ViewHolder, и это было исправлено. Похоже, что этот учебник реализует его так же, как @scompt. ком. Его точка зрения в учебнике заключается в том, что с таким ViewHolder вызов findViewById() не вызывается повторно, когда представление перерабатывается. Возможно, поэтому изображения больше не прыгают при прокрутке.

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

В моем классе адаптера: PhotoGridItem — это класс моей модели, который вводится в мое расширение ArrayAdapter, например: ArrayAdapter<PhotoGridItem>. Просто чтобы немного объяснить мой код.

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

        View row = convertView;
        final ViewHolder holder;

        if (row == null) {

            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);

            holder = new ViewHolder();
            holder.imageView = (ImageView) row.findViewById(R.id.photo_grid_view);
            // stores holder with view
            row.setTag(holder);

        } else {

            holder = (ViewHolder)convertView.getTag();
        }

        PhotoGridItem photoGridItem = getItem(position);

        if (photoGridItem != null) {
            bm = photoGridItem.getImage();
            holder.imageView.setImageBitmap(bm);

            // positioning the image in the GridView slot
            holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            holder.imageView.setLayoutParams(new LinearLayout.LayoutParams
                    (270, 270));
        }

        return row;

    }

    public class ViewHolder{
        ImageView imageView;
    }
person Azurespot    schedule 23.03.2015