Android HTML ImageGetter como AsyncTask

De acuerdo, estoy perdiendo la cabeza por esto. Tengo un método en mi progtwig que analiza HTML. Quiero incluir las imágenes en línea, y tengo la impresión de que usar Html.fromHtml (cadena, Html.ImageGetter, Html.TagHandler) permitirá que esto suceda.

Como Html.ImageGetter no tiene una implementación, me corresponde a mí escribir una. Sin embargo, como el análisis de URL en Drawables requiere acceso a la red, no puedo hacer esto en el hilo principal, por lo que debe ser una AsyncTask. Creo.

Sin embargo, cuando pasa ImageGetter como parámetro a Html.fromHtml, usa el método getDrawable que se debe anular. Así que no hay forma de llamar a la operación completa ImageGetter.exe que desencadena el método doInBackground, por lo que no hay manera de que esto sea asíncrono.

¿Lo estoy haciendo completamente mal, o peor, es esto imposible? Gracias

He hecho algo muy similar (creo) a lo que quieres hacer. Lo que tenía que hacer en ese momento es analizar el HTML y volver a configurarlo en TextView y también necesitaba usar Html.ImageGetter y tener el mismo problema al recuperar la imagen en el hilo principal.

Los pasos que hice básicamente:

  • Crear mi propia subclase para Drawable para facilitar el redibujado, lo llamé URLDrawable
  • Devuelve el URLDrawable en el método Html.ImageGetter de Html.ImageGetter
  • Una vez que se llama onPostExecute , vuelvo a dibujar el contenedor del resultado Spanned

Ahora el código para URLDrawable es el siguiente

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

Bastante simple, simplemente anulo el draw para que escoja el Drawable que coloque allí después de que termine AsyncTask.

La siguiente clase es la implementación de Html.ImageGetter y la que recupera la imagen de AsyncTask y actualiza la imagen

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

Finalmente, a continuación se muestra el progtwig de ejemplo para demostrar cómo funcionan las cosas:

 String html = "Hello " + "" + " This is a test " + ""; this.textView = (TextView)this.findViewById(R.id.textview); URLImageParser p = new URLImageParser(textView, this); Spanned htmlSpan = Html.fromHtml(html, p, null); textView.setText(htmlSpan); 

Bastante agradable. Sin embargo, el tipo DefaultHttpClient está en desuso. Pruebe esto en el método fetch:

 private InputStream fetch(String urlString) throws MalformedURLException, IOException { URL url = new URL(urlString); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream stream = urlConnection.getInputStream(); return stream; } 

Me confundí un poco, ¿está el HTML que desea convertir estático y meramente para formatear, o es dynamic y viene de la web? Si quisieras lo último, es decir, renderizar el HTML y recuperar las imágenes, será un poco molesto (sugerencia, ¿solo usar un WebView?).

De todos modos, primero debe ejecutar AsyncTask para recuperar el HTML inicial. A continuación, pasaría esos resultados al Html.fromHtml() con la implementación personalizada para la clase Html.ImageGetter . Luego, en esa implementación, debería iniciar una AsyncTask individual para recuperar cada una de las imágenes (es probable que desee implementar algo de almacenamiento en caché).

Sin embargo, al leer la documentación (y creo que he visto algunas muestras), me parece que esto no es lo que querían decir con Html.ImageGetter . Creo que está destinado para HTML codificado con referencias a drawables internos , pero esa es solo mi opinión.

si usas Picasso, cambia parte del código de @momo a

 /*** * 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()); } 

AsyncTask task = new AsyncTask () {

  @Override protected String doInBackground(Integer... params) { span = Html.fromHtml(noticeList.get(0) .getContent(), imgGetter, null); return null; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); text.setMovementMethod(ScrollingMovementMethod .getInstance()); if(span != null){ text.setText(span); } } }; task.execute();