android - voley - juegos de voleibol 3d
Vista de reciclador con solicitud de imagen de volley(solicitud de cancelaciĆ³n) (4)
Debe usar la clase ImageLoader
lugar de agregar directamente una solicitud a RequestQueue
. De esta forma, el método get()
, que se usa para obtener imágenes, devolverá un objeto de tipo ImageContainer
.
Guarde este ImageContainer
en el ViewHolder
, y cuando una vista se recicla, simplemente llame al método cancelRequest()
en la imagen reciclada para cancelar la solicitud si aún no se ha realizado.
Eche un vistazo al código de NetworkImageView
. Funciona de manera similar.
Así que estoy usando la vista de reciclador para mostrar imágenes en una cuadrícula y descargar imágenes desde la URL como mapas de bits usando la biblioteca de volley.
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);
}
El problema es cuando me desplazo y omito una o más vistas antes de que la imagen se descargue y esa vista se recicla. El requisito de carga de la imagen no se cancela en esas vistas intermedias, dando como resultado un flash de esas / esas imágenes antes de que la imagen sea cargado en esa vista.
Así que pensé en cancelar esas solicitudes de imágenes intermedias usando etiquetas, pero no puedo entender cómo se produce la cancelación de solicitudes en otras vistas paralelas.
Además, cuando uso Voley NetworkImageView (que maneja la anulación de imagen por sí mismo) da resultados perfectos. Pero necesito obtener un mapa de bits de cada imagen para elegir colores, así que no puedo usar NetworkImageView.
P) ¿Cómo cancelo todos los requisitos de imagen de volley pendientes (excepto el que debería estar cargando y sin efectuar otras vistas paralelas) en una vista de imagen específica inflada usando recyclerview?
¡Resolví el problema! yaaeeye: la respuesta de D @Itai me indicó la dirección correcta. Eché un vistazo de cerca al código de NetworkImageView y lo modifiqué de acuerdo con mi necesidad. Así que hice una 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();
}
}
Usando 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 escucha si se carga bitmap en ImageView y se llama a onSuccess si se completa la tarea. También realicé una función que devuelve el mapa de bits en la vista de la imagen y se puede usar como
Bitmap bmp = viewHolde.getmImageView.getBitmap();
Soy nuevo en Android, así que no dude en comentarme y corregirme si he hecho algo mal. Yaaaeeyeee happy dayyy
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();*/
}
}
Me enfrenté al mismo problema. No pude usar NetworkImageView
y el cargador de imágenes porque quería tener una solicitud de imagen personalizada.
Así que encontré otra forma de cancelar la solicitud de vuelo. Simplemente pasé la solicitud de imagen en el objeto onBindViewHolder
desde la onBindViewHolder
llamada onBindViewHolder
. En ViewHolder
creó un método setRequest(Request request)
.
En este método, compruebe si la solicitud no es nula, luego llame a request.cancel()
primero; de lo contrario, simplemente configure la solicitud en el titular.
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);
}