0

我正在使用 fromHTML 将 HTML 文本加载到 RecyclerView 元素内的 TextView 中。这确实有效,但是由于从 URL 加载图像并且设置或更新适配器时应用程序冻结或崩溃并且我收到日志说在主线程上完成了太多工作,因此速度非常慢。有什么方法可以使我正在使用的 HTML.fromHTML 中的 ImageGetter 更高效,并在更新时使适配器在单独的线程上运行,这样它就不会冻结应用程序?我试过寻找更快的方法来获取 Drawable,但主要的图像加载库似乎没有办法返回 Drawable 对象。

图像获取器:

private Html.ImageGetter Images = new Html.ImageGetter() {
    
    public Drawable getDrawable(String source) {

        DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
        float dpWidth = displayMetrics.widthPixels;

        int screenW = (int) dpWidth;

        Drawable drawable;

        FetchImageUrl fiu = new FetchImageUrl(context ,source);
        try {
            Boolean result = fiu.execute().get();
            drawable = fiu.getImage();
            //Log.i("source",""+source);
            //Log.i("source",""+drawable);
        }catch (Exception e) {
            Log.e("Error",""+e);
            drawable = ContextCompat.getDrawable(activity, R.drawable.image_not_found);
        }
        if(drawable!=null) {
            final float scalingFactor =
                    (float) (screenW-300) / drawable.getIntrinsicWidth();
            drawable.setBounds(0, 0, (screenW-300),
                    (int) (drawable.getIntrinsicHeight() * scalingFactor));
        }
        return drawable;

    }
};

获取图片网址:

private class FetchImageUrl extends AsyncTask<String, String, Boolean> {

        private String imageUrl;
        private Drawable image;

        public FetchImageUrl(Context context, String url) {
            this.imageUrl = url;
            image = null;
        }

        public Drawable getImage()
        {
            return image;
        }


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Boolean doInBackground(String... args) {
            try {
                InputStream input_stream = (InputStream) new URL(imageUrl).getContent();
                image = Drawable.createFromStream(input_stream, "src name");
                return true;

            }
            catch (Exception e)
            {
                Log.e("Exception",""+e);
                image = null;
            }

            return false;
        }



        @Override
        protected void onPostExecute(Boolean result) {

        }
    }
4

1 回答 1

0

看起来该行Boolean result = fiu.execute().get();阻塞了 UI 线程并且违背了AsyncTask的目的。您应该考虑使用回调onPostExecute()来设置图像。

不幸的是,网上没有很多关于如何实现Html.ImageGetter的信息。我在这里回答了一个问题,该问题解决了在模拟背景线程上加载实际图像时更改占位符图像的问题。问题中提出的解决方案也有效,但需要操作和重新扫描 HTML 文本。

我认为您可以从该帖子中改编一些内容来解决您的问题。

更新:我认为更好的解决方案是使用Glide之类的库来加载可绘制对象。如果库本身不能处理您的用例,请查看其他人如何处理限制。请参阅此处了解一种方法。我认为这个Stack Overflow 答案可能对您有用。在onResourceReady()您可以使用加载的图像设置文本。

第二次更新:我会更多地研究 Glide。您可以创建一个名为“ModelLoader”的自定义加载器,它可以获取您的流可绘制对象。有关如何编写ModelLoader的信息,请参见此处,示例请参见此处。(不知道该示例是否有效,但看起来还可以。)

于 2021-10-22T12:38:03.173 回答