所以我最近想尝试Picasso库的缓存功能,&我遇到了这种令人困惑的情况:
我检索图像'档案名称 s&来自我的网络服务器的路径(使用Retrofit2),&我将它们存储到ImageComponent
个对象(模型)中:
public class ImageComponent {
private int id; // 'id' in database
private String filename; // image name
private String path; // image path in server storage
private Bitmap bitmap;
// Overloaded constructor
// Getters & setters
}
现在加载成功,我使用 Picasso 填充RecyclerView
这些图片。加载和通胀过程是成功的,但在缓存图像时会有点棘手。
android.util.LruCache
(为方便起见,我会发布Recyclerview
适配器的完整代码。我会尽量简洁)
// imports
import android.util.LruCache;
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {
private Context mContext; // Activity's context
private List<ImageComponent> mImages; // The imageComponents to display
// The contreversial, infamous cache
private LruCache<Integer, Bitmap> mImageCache;
public ImageAdapter(Context context, List<ImageComponent> images) {
mContext = context;
mImages = images;
// Provide 1/8 of available memory to the cache
final int maxMemory = (int)(Runtime.getRuntime().maxMemory() /1024);
final int cacheSize = maxMemory / 8;
mImageCache = new LruCache<>(cacheSize);
}
@Override
public ImageAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Nothing special
}
@Override
public void onBindViewHolder(final ImageAdapter.ViewHolder holder, final int position) {
// Current ImageComponent
ImageComponent imageComponent = mImages.get(position);
// Full image path in server storage
String imagePath = Constants.SERVER_IP_ADDRESS + Constants.UPLOADS_DIRECTORY
+ imageComponent.getPath();
// Display the file's name
holder.text.setText(imageComponent.getFilename());
final ImageView imageView = holder.image;
// Get bitmap from cache, check if it exists or not
Bitmap bitmap = mImageCache.get(imageComponent.getId());
if (bitmap != null) {
Log.i("ADAPTER", "BITMAP IS NOT NULL - ID = " + imageComponent.getId());
// Image does exist in cache
holder.image.setImageBitmap(imageComponent.getBitmap());
}
else {
Log.i("ADAPTER", "BITMAP IS NULL");
// Callback to retrieve image, cache it & display it
final Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
ImageComponent img = mImages.get(position);
// Display image
holder.image.setImageBitmap(bitmap);
// Cache the image
img.setBitmap(bitmap);
mImages.set(position, img);
mImageCache.put(img.getId(), bitmap);
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
// Tag the target to the view, to keep a strong reference to it
imageView.setTag(target);
// Magic
Picasso.with(mContext)
.load(imagePath)
.into(target);
}
}
@Override
public int getItemCount() {
return mImages.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView image;
TextView text;
// Constructor & view binding, not that special
}
}
(请注意最后两张图片,以及他们在显示正确的图像之前如何显示其他先前的图片)
一些注意事项:
target
到ImageView
。 (工作)Lrucache
更加错误了(图片是随机显示,并随着每个滚动而改变),但我认为这篇文章已经足够长了。我的问题是:
Lrucache
之间的区别&amp; 毕加索&#39; (性能,最佳用例场景等......) 答案 0 :(得分:0)
我认为使用LRU缓存和Picasso会导致奇怪的行为。我使用Picasso将Image缓存到适配器,它完全正常。您可以登入here
Picasso cache当与适配器一起使用时会自动缓存,它会像这样缓存,如果list / Recycler视图的子项不可见,它将停止为相应的child缓存图像。所以最好使用Picasso单独使用适配器。
Picasso相对于LRU缓存的主要用途是,Picasso易于使用。 例如:在Picasso中指定内存缓存大小。
Picasso picasso = new Picasso.Builder(context)
.memoryCache(new LruCache(250))
.build();
Picasso还允许您在下载时出现图像时通知用户,在加载完整图像之前是Imageview的默认持有者。
希望它有所帮助。