如何将HTML内容中的内联图片保存/读取到内部/外部存储器中

11
根据这个问题,我使用了一个自定义的ImageGatter类来使用Picasso在TextView中显示我从服务器获取的图片。
    public class PicassoImageGetter implements Html.ImageGetter {

    private TextView textView = null;
    Context mContext;

    public PicassoImageGetter() {

    }

    public PicassoImageGetter(TextView target, Context context) {
        textView = target;
        mContext = context;
    }

    @Override
    public Drawable getDrawable(String source) {

        BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
        Picasso.get().load(source).into(drawable);
        return drawable;

    }

    private class BitmapDrawablePlaceHolder extends BitmapDrawable implements com.squareup.picasso.Target {

        protected Drawable drawable;

        @Override
        public void draw(final Canvas canvas) {
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
            int width = drawable.getIntrinsicWidth();
            int height = drawable.getIntrinsicHeight();
            drawable.setBounds(0, 0, width, height);
            setBounds(0, 0, width, height);
            if (textView != null) {
                textView.setText(textView.getText());
            }
        }

        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            setDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {
            setDrawable(errorDrawable);
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }

    }
}

并且像这样使用

imageGetter = new PicassoImageGetter(contentTextView, this);
    Spannable html;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        html = (Spannable) Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY, imageGetter, null);
    } else {
        html = (Spannable) Html.fromHtml(content, imageGetter, null);
    }

    contentTextView.setText(html);

我需要将这些图片存储在内部或外部存储器中,以便在没有连接时显示它们,但我不知道路径或文件名。


也许可以看一下 https://dev59.com/mI_ea4cB1Zd3GeqPU-8j],看看是否有帮助。 - owsega
请问您需要在连接不可用时从缓存中读取图像,还是希望在缓存中没有所需图像且连接不可用时显示某些默认图像? - Igor Khvostenkov
@Igor Khvostenkov,“content”包含博客页面内容,其中包含像这样的图像链接 <a href="https://1.bp.blogspot.com/-PhotHZJrpfQ/XEbV2_e_9YI/AAAAAAAAHLo/OJHTMGiwqv4n2F90IfInI2vTvQiVOiAswCLcBGAs/s1600/1546889063_680308_1546890191_rrss_normal.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="380" src="https://1.bp.blogspot.com/-PhotHZJrpfQ/XEbV2_e_9YI/AAAAAAAAHLo/OJHTMGiwqv4n2F90IfInI2vTvQiVOiAswCLcBGAs/s1600/1546889063_680308_1546890191_rrss_normal.jpg" /> 是的,如果连接不可用,我想缓存这些图像。 - Mark DeSpain
拦截你的HTTP请求并处理所有图片请求。 - Fung
1个回答

4
您需要自己实现 Picasso 缓存。具体实现方式如下:
public class PicassoCache {

    private static Picasso picassoInstance = null;

    private PicassoCache(Context context) {

        Downloader downloader = new OkHttp3Downloader(context, Integer.MAX_VALUE);
        Picasso.Builder builder = new Picasso.Builder(context);
        builder.downloader(downloader);

        picassoInstance = builder.build();
    }

    public static Picasso getPicassoInstance(Context context) {

        if (picassoInstance == null) {

            new PicassoCache(context);
            return picassoInstance;
        }

        return picassoInstance;
    }
}

然后在你的代码中:

    @Override
    public Drawable getDrawable(String source) {

        BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
        PicassoCache.getPicassoInstance(getContext()).load(source).into(drawable);
        return drawable;

    }

OkHttp3Downloader 会在您的应用程序缓存目录中安装图像缓存。您也可以使用另一个构造函数并提供自己的目录 public OkHttp3Downloader(final File cacheDir, final long maxSize)

作为替代方案,您可以使用Glide。这类似于Picasso,但还允许您显示带动画的gif,并且缓存策略在我的看法中要简单一些。

Glide.with(context)
     .load(source)
     .apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
     .into(drawable)

谢谢,这个工作得很好,但是当在setDrawable方法中没有连接时,一些图像会返回“java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()'”错误。 - Mark DeSpain
@MarkDeSpain,您能否发布完整的堆栈跟踪信息? - Igor Khvostenkov
1
@MarkDeSpain 我可以解释一下,有些情况下你尝试在没有连接且缓存中没有图像的情况下进行加载。因此,我的建议是在这种情况下从本地设备显示一些占位符图像:PicassoCache.getPicassoInstance(getContext()).load(source).placeholder(R.placeholder_image_on_local_device).into(drawable) - Igor Khvostenkov
@MarkDeSpain 应该是错误而不是占位符,在这里搞砸了:PicassoCache.getPicassoInstance(getContext()).load(source).error(R.placeholder_image_on_local_device).into(drawable) - Igor Khvostenkov
Khvostenko,不用担心,如果没有新的回答,我会在赏金最后一天完成这个任务。 - Mark DeSpain
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接