Android HTML ImageGetter作为异步任务

Android HTML ImageGetter作为异步任务,android,html-parsing,drawable,android-asynctask,Android,Html Parsing,Drawable,Android Asynctask,好吧,这件事让我发疯了。我的程序中有一个解析HTML的方法。我想包括内联图像,我的印象是使用Html.fromHtml(string,Html.ImageGetter,Html.TagHandler)可以实现这一点 因为Html.ImageGetter没有实现,所以由我来编写一个。但是,由于将URL解析为Drawables需要网络访问,我无法在主线程上执行此操作,因此它必须是一项异步任务。我想 但是,当您将ImageGetter作为参数传递给Html.fromHtml时,它使用必须重写的getD

好吧,这件事让我发疯了。我的程序中有一个解析HTML的方法。我想包括内联图像,我的印象是使用Html.fromHtml(string,Html.ImageGetter,Html.TagHandler)可以实现这一点

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

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


我是完全错了,还是更糟,这是不可能的?谢谢

我有点困惑,你想要呈现的HTML是静态的,只是为了格式化,还是动态的,来自网络?如果您想要后者,也就是渲染HTML并检索图像,那么这会有点麻烦(建议-只使用WebView?)

无论如何,您必须首先运行AsyncTask来检索初始HTML。然后,使用
Html.ImageGetter
类的自定义实现将这些结果传递到
Html.fromHtml()
。然后在该实现中,您必须启动一个单独的异步任务来检索每个图像(您可能希望实现一些缓存)


然而,通过阅读文档(我想我已经看到了一些示例),在我看来这并不是他们所说的
Html.ImageGetter
。我认为这是针对硬编码HTML的,它引用了内部可绘图项,但这只是我的看法

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

我所做的基本步骤是:

  • 为Drawable创建自己的子类以便于重画,我称之为URLDrawable
  • 返回
    Html.ImageGetter的
    getDrawable
    方法中的
    URLDrawable
  • 一旦调用了
    onPostExecute
    ,我就重新绘制了
    span
    结果的容器
现在URLDawable的代码如下


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);
        }
    }
}
很简单,我只需重写
draw
,这样它就可以在任务完成后选择我在那里设置的可绘制文件

下面的类是
Html.ImageGetter
的实现,它从
AsyncTask
获取图像并更新图像

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();
        }
    }
}
公共类URLImageParser实现ImageGetter{
上下文c;
视图容器;
/***
*构造URLImageParser,它将执行AsyncTask并刷新容器
*@param t
*@param c
*/
公共URLImageParser(视图t,上下文c){
这个.c=c;
这个容器=t;
}
公共可绘制getDrawable(字符串源){
URLDAWABLE URLDAWABLE=新的URLDAWABLE();
//获取实际来源
ImageGetterAsyncTask异步任务=
新的ImageGetterAsyncTask(URLDawable);
asyncTask.execute(源代码);
//返回对URLDrawable的引用,其中我将根据实际图像进行更改
//src标签
返回可提取;
}
公共类ImageGetterAsyncTask扩展异步任务{
URLDrawable URLDrawable;
公共ImageGetterAsyncTask(URLDawable d){
this.urlDrawable=d;
}
@凌驾
受保护的可抽出式doInBackground(字符串…参数){
字符串源=参数[0];
返回可提取的(源);
}
@凌驾
受保护的void onPostExecute(可提取结果){
//根据HTTP调用的结果设置正确的绑定
urlDrawable.setBounds(0,0,0+result.getIntrinsicWidth(),0
+result.getIntrinsicHeight());
//将当前绘图的参考更改为结果
//从HTTP调用
urlDrawable.drawable=结果;
//通过使容器无效来重新绘制图像
URLImageParser.this.container.invalidate();
}
/***
*从URL获取可绘制的内容
*@param-urlString
*@返回
*/
公共可提取可提取(字符串urlString){
试一试{
InputStream is=fetch(urlString);
Drawable Drawable=Drawable.createFromStream(是“src”);
setBounds(0,0,0+drawable.getIntrinsicWidth(),0
+getIntrinsicHeight());
回拉;
}捕获(例外e){
返回null;
} 
}
私有InputStream获取(字符串urlString)引发错误的InputStream异常,IOException{
DefaultHttpClient httpClient=新的DefaultHttpClient();
HttpGet请求=新的HttpGet(urlString);
HttpResponse response=httpClient.execute(请求);
返回response.getEntity().getContent();
}
}
}
最后,下面是演示如何工作的示例程序:

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);
String html=“你好”+
"" +
“这是一个测试”+
"";
this.textView=(textView)this.findViewById(R.id.textView);
URLImageParser p=新的URLImageParser(textView,this);
span htmlSpan=Html.fromHtml(Html,p,null);
setText(htmlSpan);

AsyncTask任务=新的AsyncTask(){


非常好。但是,类型DefaultHttpClient已被弃用。请在获取方法上尝试此方法:

private InputStream fetch(String urlString) throws MalformedURLException, IOException {

        URL url = new URL(urlString);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        InputStream stream = urlConnection.getInputStream();

        return stream;

    }

如果您使用毕加索,请将@momo代码的一部分更改为

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

        private Drawable fetch(String urlString) throws MalformedURLException, IOException {
            return new BitmapDrawable(c.getResources(), Picasso.with(c).load(urlString).get());
        }
我是p
/***
         * Get the Drawable from URL
         * @param urlString
         * @return
         */
        public Drawable fetchDrawable(String urlString) {
            try {
                Drawable drawable = fetch(urlString);
                drawable.setBounds(0, 0, 0 + drawable.getIntrinsicWidth(), 0
                        + drawable.getIntrinsicHeight());
                return drawable;
            } catch (Exception e) {
                return null;
            }
        }

        private Drawable fetch(String urlString) throws MalformedURLException, IOException {
            return new BitmapDrawable(c.getResources(), Picasso.with(c).load(urlString).get());
        }