gpt4 book ai didi

android - 如何使 Picasso/Glide 与 Html.ImageGetter 一起缓存图像?

转载 作者:行者123 更新时间:2023-12-02 21:13:57 24 4
gpt4 key购买 nike

感谢@Budius 所做的一切努力。

我的应用程序的大部分图像工作可以由 Picasso/Glide 处理,但是,某些图像显示在 TextView 中通过Html.fromHtml 。以及 TextView 中的图像也经常使用。

但是,我不知道如何实现getDrawable()使用 Picasso/Glide 的方法 ImageGetter传递至Html.fromHtml 。是否可以为TextView中的这些图片共享Picasso/Glide相同的缓存和其他位图?

或者我应该使用自定义 LruCache相反,以 ImageGetter 形式缓存这些图片分别地?这种方式会增加 OOM 错误的风险吗?而且我认为使用两个不同的系统来处理图像会产生不必要的工作量。

更新:我尝试使用.get() picasso ,但医生说

/**
* 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中的图像会出现一些奇怪的行为。 。有时,除非切换到另一个应用程序再切换回来,否则图像无法刷新,并且图像位置严重不正确。

更新:我已在下面发布了所有用于测试的代码。仍然存在一些错误。如果没有占位符,它仍然会抛出 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();
}
}

测试 Activity

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下载图像。

在下面的链接中你可以找到一个 DrawableWrapper,它来自 Google 的支持库,但它不是公共(public)文档的一部分,所以我只需将整个代码复制到你的项目中 https://android.googlesource.com/platform/frameworks/support/+/master/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableWrapper.java

然后您可以从中创建一个 PicassoTargetDrawable

public class PicassoTargetDrawable extends DrawableWrapper
implements Picasso.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 void Drawable getDrawable(String source) {
PicassoTargetDrawable d = new PicassoTargetDrawable(context);
Picasso.with(context)
.load(source)
..... add here onError and placeholder drawables
.into(d);
return d;
}

附注:我写的这些都没有查太多资料,可能会有一些错别字和一些需要整理的问题,但是对于你理解这个概念来说肯定足够了。

更新:只是更正您的代码。

TextView 已经告诉 WrapDrawable 它应该使用的边界。如果您告诉新的 mDrawable 它可以使用它想要的任何尺寸,它就会使用它想要的任何尺寸。因此,您应该传递赋予 WrapDrawable 的大小,而不是传递其自身的固有宽度/高度

public void setWrappedDrawable(Drawable drawable) {
if (mDrawable != null) {
mDrawable.setCallback(null);
}
mDrawable = drawable;
if (drawable != null) {
mDrawable.setBounds(getBounds());
drawable.setCallback(this);
}
}

关于android - 如何使 Picasso/Glide 与 Html.ImageGetter 一起缓存图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33040002/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com