Android的HTML ImageGetter为AsyncTask的HTML、Android、AsyncTask、ImageGetter

2023-09-11 11:39:21 作者:逃不出思念的魔爪

好了,我失去了我的脑海里这一个。我在我的程序中的方法,该方法解析HTML。我想包括内嵌图像,而我下,使用的Html.fromHtml(字符串,Html.ImageGetter,Html.TagHandler)的IM pression将允许这样的事情发生。

Okay, I'm losing my mind over this one. I have a method in my program which parses HTML. I want to include the inline images, and I am under the impression that using the Html.fromHtml(string, Html.ImageGetter, Html.TagHandler) will allow this to happen.

由于Html.ImageGetter没有实现,它给我写一个。然而,由于解析URL到可绘制需要访问网络,我不能在主线程中做到这一点,所以它必须是一个AsyncTask的。我想。

Since Html.ImageGetter doesn't have an implementation, it's up to me to write one. However, since parsing URLs into Drawables requires network access, I can't do this on the main thread, so it must be an AsyncTask. I think.

不过,当您通过ImageGetter作为参数传递给Html.fromHtml,它采用了必须覆盖的getDrawable方法。因此,有没有办法来调用整个ImageGetter.execute交易触发doInBackground方法,所以没有办法真正让这个异步的。

However, when you pass the ImageGetter as a parameter to Html.fromHtml, it uses the getDrawable method that must be overridden. So there's no way to call the whole ImageGetter.execute deal that triggers the doInBackground method, and so there's no way to actually make this asynchronous.

我是不是这件事完全错误的,或者更糟糕,这是不可能的?谢谢

Am I going about it completely wrong, or worse, is this impossible? Thanks

推荐答案

我已经做了一些非常相似的(我觉得)你想要做什么。我需要做的当时是解析HTML并设置它回TextView的,我需要使用 Html.ImageGetter 以及具有上获取的图像同样的问题主线程。

I've done something very similar (I think) to what you want to do. What I needed to do back then is parse the HTML and set it up back to TextView and I needed to use Html.ImageGetter as well and having the same problem on fetching image on the main thread.

这是我做了基本的步骤:

The steps that I did basically:

创建我自己的子类用于绘制对象,以方便重绘,我把它叫做URLDrawable 返回 URLDrawable getDrawable 的方法 Html.ImageGetter onPostExecute 叫,我重绘的跨区结果容器 Create my own subclass for Drawable to facilitate redraw, I called it URLDrawable Return the URLDrawable in getDrawable method of Html.ImageGetter Once onPostExecute is called, I redraw the container of the Spanned result

现在的$ C $下URLDrawable是如下

Now the code for URLDrawable is as follow


public class URLDrawable extends BitmapDrawable {
    // the drawable that you need to set, you could set the initial drawing
    // with the loading image if you need to
    protected Drawable drawable;

    @Override
    public void draw(Canvas canvas) {
        // override the draw to facilitate refresh function later
        if(drawable != null) {
            drawable.draw(canvas);
        }
    }
}

很简单,我只是覆盖所以就挑了绘制对象,我设置在那里的AsyncTask结束后。

Simple enough, I just override draw so it would pick the Drawable that I set over there after AsyncTask finishes.

下面的类是 Html.ImageGetter 的实施和一个取该图像由的AsyncTask 和更新图像

The following class is the implementation of Html.ImageGetter and the one that fetches the image from AsyncTask and update the image

public class URLImageParser implements ImageGetter {
    Context c;
    View container;

    /***
     * Construct the URLImageParser which will execute AsyncTask and refresh the container
     * @param t
     * @param c
     */
    public URLImageParser(View t, Context c) {
        this.c = c;
        this.container = t;
    }

    public Drawable getDrawable(String source) {
        URLDrawable urlDrawable = new URLDrawable();

        // get the actual source
        ImageGetterAsyncTask asyncTask = 
            new ImageGetterAsyncTask( urlDrawable);

        asyncTask.execute(source);

        // return reference to URLDrawable where I will change with actual image from
        // the src tag
        return urlDrawable;
    }

    public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable>  {
        URLDrawable urlDrawable;

        public ImageGetterAsyncTask(URLDrawable d) {
            this.urlDrawable = d;
        }

        @Override
        protected Drawable doInBackground(String... params) {
            String source = params[0];
            return fetchDrawable(source);
        }

        @Override
        protected void onPostExecute(Drawable result) {
            // set the correct bound according to the result from HTTP call
            urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0 
                    + result.getIntrinsicHeight()); 

            // change the reference of the current drawable to the result
            // from the HTTP call
            urlDrawable.drawable = result;

            // redraw the image by invalidating the container
            URLImageParser.this.container.invalidate();
        }

        /***
         * Get the Drawable from URL
         * @param urlString
         * @return
         */
        public Drawable fetchDrawable(String urlString) {
            try {
                InputStream is = fetch(urlString);
                Drawable drawable = Drawable.createFromStream(is, "src");
                drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0 
                        + drawable.getIntrinsicHeight()); 
                return drawable;
            } catch (Exception e) {
                return null;
            } 
        }

        private InputStream fetch(String urlString) throws MalformedURLException, IOException {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet request = new HttpGet(urlString);
            HttpResponse response = httpClient.execute(request);
            return response.getEntity().getContent();
        }
    }
}

最后,下面是示例程序演示是如何工作的:

Finally, below is the sample program to demonstrate how things work:

String html = "Hello " +
"<img src='http://www.gravatar.com/avatar/" + 
"f9dd8b16d54f483f22c0b7a7e3d840f9?s=32&d=identicon&r=PG'/>" +
" This is a test " +
"<img src='http://www.gravatar.com/avatar/a9317e7f0a78bb10a980cadd9dd035c9?s=32&d=identicon&r=PG'/>";

this.textView = (TextView)this.findViewById(R.id.textview);
URLImageParser p = new URLImageParser(textView, this);
Spanned htmlSpan = Html.fromHtml(html, p, null);
textView.setText(htmlSpan);