RecyclerView消失的图像
我想创建的是一个水平滚动图像库。 我有一个RecyclerView(支持22.0.0)。 我遇到的问题是,当我滚动到结尾然后向后滚动时,通常一个图像有时会丢失两个。 奇怪的是,当我不停地来回滑动时,不同的图像可能会丢失。 这是该项目的布局:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="160dp">
<ImageView
android:id="@+id/product_variation_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:layout_gravity="center"/>
这是Adaper:
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public ViewHolder(View v) {
super(v);
mImageView = (ImageView) v.findViewById(R.id.product_variation_image);
}
}
public TestAdapter(String[] myDataset) {
mDataset = myDataset;
}
@Override
public TestAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.variaton_list_item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mImageView.setImageDrawable(null);
String url = mDataset[position];
Log.i("TEST", "position = " + position);
((MainActivity)MainActivity.getInstance()).imageDownloader.download(url, holder.mImageView);
}
@Override
public int getItemCount() {
return mDataset.length;
}
下载方法从URL中获取图像,或者如果已缓存,则从内存获取图像。 这适用于所有其他布局,例如ListView或GridView。 这里是我用来在Fragment中设置的代码:
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(layoutManager);
这是在onCreateView方法中。 当我得到网址时,我填充它们并使用以下命令设置适配器:
myDataset[i] = imageURL; // for each image
mAdapter = new TestAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
有趣的是适配器中的onBindViewHolder方法中的行,我在这里记录了位置。 我发现的是,图像不显示的单元格是这种方法没有被调用。 这就像是由于某种原因正在跳过那个小区。 更奇怪的是,如果我持有一个单元格并从左向右滑动,如果一个单元格离开屏幕然后又回来,它的图像就会消失,onBindViewHolder方法也不会被调用。
我认为不重要的一类是造成问题的那一类。 我不确定是什么原因,但它驻留在我用于从BitmapFun样本获取的循环中使用的自定义ImageView类中。
public class RecyclingImageView extends ImageView {
public RecyclingImageView(Context context) {
super(context);
}
public RecyclingImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* @see android.widget.ImageView#onAttachedToWindow()
*/
@Override
protected void onAttachedToWindow() {}
/**
* @see android.widget.ImageView#onDetachedFromWindow()
*/
@Override
protected void onDetachedFromWindow() {
// This has been detached from Window, so clear the drawable
setImageDrawable(null);
super.onDetachedFromWindow();
}
/**
* @see android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)
*/
@Override
public void setImageDrawable(Drawable drawable) {
// Keep hold of previous Drawable
final Drawable previousDrawable = getDrawable();
// Call super to set new Drawable
super.setImageDrawable(drawable);
// Notify new Drawable that it is being displayed
notifyDrawable(drawable, true);
// Notify old Drawable so it is no longer being displayed
notifyDrawable(previousDrawable, false);
}
/**
* Notifies the drawable that it's displayed state has changed.
*
* @param drawable
* @param isDisplayed
*/
private static void notifyDrawable(Drawable drawable, final boolean isDisplayed) {
if (drawable instanceof RecyclingBitmapDrawable) {
// The drawable is a CountingBitmapDrawable, so notify it
((RecyclingBitmapDrawable) drawable).setIsDisplayed(isDisplayed);
} else if (drawable instanceof LayerDrawable) {
// The drawable is a LayerDrawable, so recurse on each layer
LayerDrawable layerDrawable = (LayerDrawable) drawable;
for (int i = 0, z = layerDrawable.getNumberOfLayers(); i < z; i++) {
notifyDrawable(layerDrawable.getDrawable(i), isDisplayed);
}
}
}
}
当我用普通的ImageView替换它时,我不再会遇到问题。
有可能测试一些东西吗? 你可以使用这个库来加载URL中的图像吗? http://square.github.io/picasso/它缓存所有内容,并以异步方式处理所有内容。
使用它像...
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Picasso.with(mImageView.getContext()).cancelRequest(holder.mImageView);
String url = mDataset[position];
Picasso.with(mImageView.getContext()).load(url).placeholder(R.drawable.placeholder).into(holder.mImageView);
}
...并看看它是否仍然不显示一些图像。 如果是这样,那么至少你会100%确定问题不在你的下载机制中(我认为这可能是)。
如果你使用的是Android Studio
那么只需添加依赖compile 'com.squareup.picasso:picasso:2.5.2'
,如果不是,你可以添加你在上面链接找到的库。
值得一试 ...
我们可以通过扩展LinearLayoutManager和ImageView来解决这个问题。
1.创建一个PrecachingLinearLayoutManager
public class PrecachingLinearLayoutManager extends LinearLayoutManager {
private static final int DEFAULT_EXTRA_LAYOUT_SPACE = 600;
private int extraLayoutSpace = -1;
@SuppressWarnings("unused")
private Context mContext;
public PrecachingLinearLayoutManager(Context context) {
super(context);
this.mContext = context;
}
public PrecachingLinearLayoutManager(Context context, int extraLayoutSpace) {
super(context);
this.mContext = context;
this.extraLayoutSpace = extraLayoutSpace;
}
public PrecachingLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
this.mContext = context;
}
public void setExtraLayoutSpace(int extraLayoutSpace) {
this.extraLayoutSpace = extraLayoutSpace;
}
@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
if (extraLayoutSpace > 0) {
return (extraLayoutSpace);
}
return (DEFAULT_EXTRA_LAYOUT_SPACE);
}
}
2.使用PrecachingLinearLayoutManager替换LinearLayoutManager
DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
PrecachingLinearLayoutManager layout = new PrecachingLinearLayoutManager(getActivity());
layout.setExtraLayoutSpace(displayMetrics.heightPixels);
recyclerview.setLayoutManager(layout);
3.创建一个RecycleImageView
private Object tag = null;
@Override
protected void onAttachedToWindow() {
Object tag = getTag();
if (tag == null || !tag.equals(this.tag)) {
// Will cause displayed bitmap wrapper to
// be 'free-able'
setImageDrawable(null);
this.tag = null;
super.onDetachedFromWindow();
}
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
Object tag = getTag();
if (tag != null) {
this.tag = tag;
} else {
// Will cause displayed bitmap wrapper to
// be 'free-able'
setImageDrawable(null);
this.tag = null;
super.onDetachedFromWindow();
}
}
4.使用RecycleImageView替换ImageView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:extends="http://schemas.android.com/apk/res/com.yourdomain.yourpackage"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/viewgroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<com.yourdomain.yourpackage.RecycleImageView
android:id="@+id/photo"
android:layout_width="40dp"
android:layout_height="40dp"
extends:delayable="true"
android:contentDescription="@string/nothing"
android:src="@drawable/photo_placeholder" >
</com.yourdomain.yourpackage.RecycleImageView>
</LinearLayout>
链接地址: http://www.djcxy.com/p/25517.html