【问题标题】:Recycler view with volley image request (cancel request)带有凌空图像请求的回收器视图(取消请求)
【发布时间】:2014-10-27 15:45:53
【问题描述】:

所以我使用回收器视图在网格中显示图像,并使用 volley 库从 url 下载图像作为位图。

public void onBindViewHolder(final TrendingAdapter.ViewHolder viewHolder, int i) {
    ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
        @Override
        public void onResponse(Bitmap bitmap) {
            if (bitmap != null) {
                viewHolder.getmImageView().setImageBitmap(bitmap);
            }
        }
    }, 0, 0, null,
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                }
            });
    AppController.getInstance().addToRequestQueue(request);
}

问题是,当我在下载图像之前滚动并跳过一个或多个视图并且该视图被回收时,图像下载请求不会在那些中间视图上取消,导致该/那些图像在实际图像加载到该视图中。

所以我想使用标签取消那些中间图像请求,但无法弄清楚它是如何导致在其他并行视图中取消请求的!

此外,当我使用 volley NetworkImageView(自行处理此类图像取消)时,效果也很完美。但我需要获取每个图像的位图以从中选择颜色,因此我无法使用 NetworkImageView。

问)如何取消使用 recyclerview 膨胀的特定图像视图上的所有待处理的凌空图像请求(除了应该加载且不影响其他并行视图的请求)?

【问题讨论】:

  • 让 ViewHolder 包含请求...检查 ViewHolder.request 是否不为空,并在创建新请求之前调用 ViewHolder.request.cancel ...
  • 您还可以扩展网络图像视图,并在收到位图后根据需要提供给我们。
  • 谢谢大家!我们成功了^.^

标签: android bitmap android-volley android-recyclerview android-viewholder


【解决方案1】:

您应该使用ImageLoader 类而不是直接向RequestQueue 添加请求。这样,用于获取图像的get() 方法将返回ImageContainer 类型的对象。

将此ImageContainer保存在ViewHolder中,当视图被回收时,只需在回收的图像上调用cancelRequest()方法即可取消请求(如果尚未执行)。

查看NetworkImageView 的代码。它以类似的方式工作。

【讨论】:

  • 嘿,谢谢!你让我想到了正确的路径。我制作了一个 CustomNetworkImageView 并将代码发布为 ans。另外,如果你能帮助我,我想从位图中挑选颜色。什么会更好? a) 从 imageView 中获取位图,然后获取颜色 b) 将 getColors 的代码放入 CustomNetwork... 并询问 CustomNetw.. 获取 getColors 吗?
  • 无论哪种方式都应该没问题,看看什么对您的代码更有意义。
【解决方案2】:

我解决了这个问题! yaaeeye :D @Itai 的回答为我指明了正确的方向。我仔细查看了 NetworkImageView 代码并根据需要对其进行了修改。所以我做了一个 CustumNetworkImageView

public class CustomNetworkImageView extends ImageView {

    // Added code block start

    public interface ResponseObserver {
        public void onError();

        public void onSuccess();
    }

    private ResponseObserver mResponseObserver;

    public void setmResponseObserver(ResponseObserver observer) {
        mResponseObserver = observer;
    }

    private Bitmap bmp = null;

    // Added code block end

    private String mUrl;

    private int mDefaultImageId;

    private int mErrorImageId;

    private ImageLoader mImageLoader;

    public CustomNetworkImageView(Context context) {
        this(context, null);
    }

    public CustomNetworkImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setImageUrl(String url, ImageLoader imageLoader) {
        mUrl = url;
        mImageLoader = imageLoader;
        loadImageIfNecessary();
    }

    public void setDefaultImageResId(int defaultImage) {
        mDefaultImageId = defaultImage;
    }

    public void setErrorImageResId(int errorImage) {
        mErrorImageId = errorImage;

        // Added code block start

        if (mResponseObserver != null) {
            mResponseObserver.onError();
        }

        // Added code block end

    }

    // Added code block start

    public Bitmap getBitmap() {
        return bmp;
    }

    // Added code block end

    private void loadImageIfNecessary() {
        int width = getWidth();
        int height = getHeight();

        if (width == 0 && height == 0) {
            return;
        }

        if (TextUtils.isEmpty(mUrl)) {
            ImageContainer oldContainer = (ImageContainer) getTag();
            if (oldContainer != null) {
                oldContainer.cancelRequest();
                setImageBitmap(null);
            }
            return;
        }

        ImageContainer oldContainer = (ImageContainer) getTag();

        if (oldContainer != null && oldContainer.getRequestUrl() != null) {
            if (oldContainer.getRequestUrl().equals(mUrl)) {

                return;
            } else {

                oldContainer.cancelRequest();
                setImageBitmap(null);
            }
        }

        ImageContainer newContainer = mImageLoader.get(mUrl,
                ImageLoader.getImageListener(this, mDefaultImageId, mErrorImageId));

        setTag(newContainer);

        final Bitmap bitmap = newContainer.getBitmap();
        if (bitmap != null) {

            setImageBitmap(bitmap);

           // Added code block start

            bmp = bitmap;
            if (mResponseObserver != null) {
                mResponseObserver.onSuccess();
            }

           // Added code block end
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        loadImageIfNecessary();
    }

    @Override
    protected void onDetachedFromWindow() {
        ImageContainer oldContainer = (ImageContainer) getTag();
        if (oldContainer != null) {

            oldContainer.cancelRequest();
            setImageBitmap(null);

            setTag(null);
        }
        super.onDetachedFromWindow();
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        invalidate();
    }
}

使用 CustomNetworkImageView :

    viewHolder.getmImageView().setImageUrl(wallThumb.get(i), AppController.getInstance().getImageLoader());

    viewHolder.getmImageView().setmResponseObserver(new CustomNetworkImageView.ResponseObserver() {

            @Override
            public void onError() {
            }

            @Override
            public void onSuccess() {
                // Image is loaded in ImageView.. Do Something..
                Bitmap bitmap = viewHolder.getmImageView().getBitmap();
            }
        });

SetmResponseObserver 监听 ImageView 中是否加载了位图,如果任务完成则调用 onSuccess。我还做了一个函数,它返回图像视图上的位图,可以用作

Bitmap bmp = viewHolde.getmImageView.getBitmap();

我是 android 新手,所以如果我做错了什么,请随时发表评论并纠正我。 Yaaaeeyeee 快乐每一天

【讨论】:

  • 什么是getmImageView() ??
  • 嗨@umar,因为我正在使用带有回收器视图的视图持有者模式,getmImageView() 是一个吸气剂,它返回我膨胀的图像视图。在这种情况下,因为我使用的是CustomNetworkImageView getmImageView() 返回相同的实例..
【解决方案3】:
public class RecyclerViewPagerNetworkImageView extends NetworkImageView {
public RecyclerViewPagerNetworkImageView(Context context) {
    super(context);
}

public RecyclerViewPagerNetworkImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public RecyclerViewPagerNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onDetachedFromWindow() {
    // delete
    /*if (mImageContainer != null) {
        // If the view was bound to an image request, cancel it and clear
        // out the image from the view.
        mImageContainer.cancelRequest();
        setImageBitmap(null);
        // also clear out the container so we can reload the image if necessary.
        mImageContainer = null;
    }
    super.onDetachedFromWindow();*/
}

}

【讨论】:

    【解决方案4】:

    我遇到了同样的问题。我无法使用NetworkImageView 和图像加载器,因为我想要一个自定义图像请求。

    所以我找到了另一种取消航班请求的方法。我只是从onBindViewHolder 回调中传递了ViewHolder 对象中的图像请求。在ViewHolder 中创建了一个方法setRequest(Request request)

    在此方法中检查请求是否为空,然后首先调用request.cancel(),否则只需将请求设置为持有者。

    public class ViewHolder extends RecyclerView.ViewHolder {
    
        public Request request;
    
        public ViewHolder(View view) {
            super(view);
        }
    
        public void setRequest(Request request) {
           if (this.request != null) {
                this.request.cancel();
           }
           this.request = request;
        }
    }
    
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    
            ImageRequest imageRequest = new ImageRequest(.......);
            holder.setRequest(request);
    
            mRequestQueue.add(request);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 2021-05-03
      相关资源
      最近更新 更多