Android HTML ImageGetter 作为 AsyncTask [英] Android HTML ImageGetter as AsyncTask

查看:53
本文介绍了Android HTML ImageGetter 作为 AsyncTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我对这个失去了理智.我的程序中有一个解析 HTML 的方法.我想包含内嵌图像,我的印象是使用 Html.fromHtml(string, Html.ImageGetter, Html.TagHandler) 将允许这种情况发生.

由于 Html.ImageGetter 没有实现,所以由我来编写.但是,由于将 URL 解析为 Drawables 需要网络访问,因此我无法在主线程上执行此操作,因此必须是 AsyncTask.我想.

但是,当您将 ImageGetter 作为参数传递给 Html.fromHtml 时,它使用必须覆盖的 getDrawable 方法.因此,无法调用触发 doInBackground 方法的整个 ImageGetter.execute 处理,因此无法真正实现异步.

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

解决方案

我做过一些(我认为)与您想做的非常相似的事情.当时我需要做的是解析 HTML 并将其设置回 TextView,我还需要使用 Html.ImageGetter 并且在主线程上获取图像时遇到同样的问题.>

我基本上做的步骤:

  • 为 Drawable 创建我自己的子类以方便重绘,我称之为 URLDrawable
  • 返回Html.ImageGettergetDrawable方法中的URLDrawable
  • 一旦onPostExecute被调用,我会重绘Spanned结果的容器

现在 URLDrawable 的代码如下

<代码>公共类 URLDrawable 扩展 BitmapDrawable {//需要设置的drawable,可以设置初始绘图//如果需要,带有加载图像受保护的 Drawable drawable;@覆盖公共无效绘制(帆布画布){//覆盖绘制以方便后面的刷新功能如果(可绘制!= null){drawable.draw(画布);}}}

很简单,我只是覆盖了 draw,这样它就会在 AsyncTask 完成后选择我在那里设置的 Drawable.

下面的类是Html.ImageGetter的实现,也是从AsyncTask中获取图片并更新图片的类

公共类 URLImageParser 实现 ImageGetter {上下文 c;查看容器;/**** 构造 URLImageParser,它将执行 AsyncTask 并刷新容器* @param t* @param c*/公共 URLImageParser(查看 t,上下文 c){this.c = c;this.container = t;}public Drawable getDrawable(字符串源){URLDrawable urlDrawable = new URLDrawable();//获取实际来源ImageGetterAsyncTask asyncTask =新 ImageGetterAsyncTask( urlDrawable);asyncTask.execute(source);//返回对 URLDrawable 的引用,我将在其中更改实际图像//src 标签返回 urlDrawable;}公共类 ImageGetterAsyncTask 扩展了 AsyncTask{URLDrawable urlDrawable;公共 ImageGetterAsyncTask(URLDrawable d) {this.urlDrawable = d;}@覆盖受保护的 Drawable doInBackground(String... params) {字符串源 = params[0];返回 fetchDrawable(source);}@覆盖protected void onPostExecute(Drawable 结果) {//根据 HTTP 调用的结果设置正确的边界urlDrawable.setBounds(0, 0, 0 + result.getIntrinsicWidth(), 0+ result.getIntrinsicHeight());//将当前可绘制对象的引用更改为结果//来自 HTTP 调用urlDrawable.drawable = 结果;//通过使容器无效来重绘图像URLImageParser.this.container.invalidate();}/**** 从 URL 获取 Drawable* @param urlString* @返回*/公共可绘制 fetchDrawable(String urlString) {尝试 {InputStream 是 = fetch(urlString);Drawable drawable = Drawable.createFromStream(is, "src");drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0+ drawable.getIntrinsicHeight());返回可绘制;} 捕获(异常 e){返回空;}}私有 InputStream fetch(String urlString) 抛出 MalformedURLException, IOException {DefaultHttpClient httpClient = new DefaultHttpClient();HttpGet 请求 = 新的 HttpGet(urlString);HttpResponse 响应 = httpClient.execute(request);返回 response.getEntity().getContent();}}}

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

String html = "你好" +"<img src='http://www.gravatar.com/avatar/" +"f9dd8b16d54f483f22c0b7a7e3d840f9?s=32&d=identicon&r=PG'/>"+这是一个测试" +"<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);跨越的 htmlSpan = Html.fromHtml(html, p, null);textView.setText(htmlSpan);

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.

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.

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

解决方案

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:

  • 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

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);
        }
    }
}

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

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);

这篇关于Android HTML ImageGetter 作为 AsyncTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆