【发布时间】:2015-10-09 13:50:05
【问题描述】:
感谢@Budius 所做的所有努力。
我的应用程序的大部分图像工作可以由 Picasso/Glide 处理,但是,一些图像由Html.fromHtml 显示在TextView 中。而且TextView中的图片也经常被使用。
但是,对于传递给Html.fromHtml 的ImageGetter,我不知道如何使用Picasso/Glide 实现getDrawable() 方法。是否可以为TextView 和其他位图中的这些图片共享同一个 Picasso/Glide 缓存?
或者我应该使用自定义LruCache 来分别缓存ImageGetter 中的这些图片吗?这种方式会增加OOM错误的风险吗?而且我认为使用 2 个不同的系统处理图像会产生不必要的工作量。
更新:我尝试使用毕加索的.get(),但文档说
/**
* The result of this operation is not cached in memory because the underlying
* {@link Cache} implementation is not guaranteed to be thread-safe.
*/
所以在这种情况下不使用缓存。
更新:
@Budius 的答案是对的,但是缺少为Drawable 设置边界的代码,导致Drawable 没有显示在TextView 中。于是我将DrawableWrapper类中的代码修改为:
public void setWrappedDrawable(Drawable drawable) {
if (mDrawable != null) {
mDrawable.setCallback(null);
}
mDrawable = drawable;
if (drawable != null) {
mDrawable.setBounds(0,0,mDrawable.getIntrinsicWidth(),mDrawable.getIntrinsicHeight());
drawable.setCallback(this);
}
}
更新:,问题仍未解决。如果您实施上述解决方案,TextView 中的图像会出现一些奇怪的行为。有时候图片无法刷新,除非你切换到另一个应用再切换回来,而且图片的位置严重不正确。
更新:我已经在下面发布了所有测试代码。还是有一些bug。如果没有占位符,它仍然会抛出 NPE。使用占位符,行为很奇怪。我第一次输入TestActivity,它会显示占位符,但不会变成下载的图片。但是当我切换到另一个应用程序或按下返回按钮并再次输入TestActivity 后,会显示图片(可能是因为它在缓存中?)。
而且图片的大小是正确的,但仍然没有留下图像的位置。如果我调用mDrawable.setBounds(getBounds()); 而不是mDrawable.setBounds(0,0,getIntrinsicWidth(),getIntrinsicHeight());,它将不会显示。
DrawableWrapper
public class DrawableWrapper extends Drawable implements Drawable.Callback {
private Drawable mDrawable;
public DrawableWrapper(Drawable drawable) {
setWrappedDrawable(drawable);
}
@Override
public void draw(Canvas canvas) {
mDrawable.draw(canvas);
}
@Override
public int getIntrinsicWidth() {
return 384;
}
@Override
public int getIntrinsicHeight() {
return 216;
}
//... other delegation methods are omitted
public void setWrappedDrawable(Drawable drawable) {
if (mDrawable != null) {
mDrawable.setCallback(null);
}
mDrawable = drawable;
if (drawable != null) {
mDrawable.setBounds(0,0,getIntrinsicWidth(),getIntrinsicHeight());
drawable.setCallback(this);
}
}
}
PicassoTargetDrawable
public class PicassoTargetDrawable extends DrawableWrapper
implements Target {
private Context context;
public PicassoTargetDrawable(Context context) {
super(new ColorDrawable(0));
// use application context to not leak activity
this.context = context.getApplicationContext();
}
public void onBitmapFailed(Drawable errorDrawable) {
setWrappedDrawable(errorDrawable);
invalidateSelf();
}
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setWrappedDrawable(new BitmapDrawable(context.getResources(), bitmap));
context = null;
invalidateSelf();
}
public void onPrepareLoad(Drawable placeHolderDrawable) {
setWrappedDrawable(placeHolderDrawable);
invalidateSelf();
}
}
测试活动
public class TestActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
setContentView(textView);
String html = "<div>test<br/>" +
"<img src=\"http://i2.cdn.turner.com/money/dam/assets/150910165544-elon-evo-open-still-384x216.png\"></img>" +
"<br/>/test</div>";
textView.setText(Html.fromHtml(html, new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
PicassoTargetDrawable d = new PicassoTargetDrawable(TestActivity.this);
Picasso.with(TestActivity.this)
.load(source)
//add placeholder here
.into(d);
return d;
}
}, null));
}
}
【问题讨论】:
-
你能从Picasso的
Target得到的Bitmap制作一个BitmapDrawable吗? -
我认为这是一个异步进程,所以它不适用于
getDrawable()。您能否更具体地说明如何编码?
标签: android caching picasso android-bitmap android-glide