Android: cargando una imagen desde la Web con Asynctask

¿Cómo reemplazo las siguientes líneas de código con Asynctask? ¿Cómo “recuperas” el bitmap de Asynctask? Gracias.

ImageView mChart = (ImageView) findViewById(R.id.Chart); String URL = "http://www...anything ..."; mChart.setImageBitmap(download_Image(URL)); public static Bitmap download_Image(String url) { //--------------------------------------------------- Bitmap bm = null; try { URL aURL = new URL(url); URLConnection conn = aURL.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bm = BitmapFactory.decodeStream(bis); bis.close(); is.close(); } catch (IOException e) { Log.e("Hub","Error getting the image from server : " + e.getMessage().toString()); } return bm; //--------------------------------------------------- } 

Pensé en algo como esto:

reemplazar:

 mChart.setImageBitmap(download_Image(graph_URL)); 

por algo como:

 mChart.setImageBitmap(new DownloadImagesTask().execute(graph_URL)); 

y

 public class DownloadImagesTask extends AsyncTask { @Override protected Bitmap doInBackground(String... urls) { return download_Image(urls[0]); } @Override protected void onPostExecute(Bitmap result) { mChart.setImageBitmap(result); // how do I pass a reference to mChart here ? } private Bitmap download_Image(String url) { //--------------------------------------------------- Bitmap bm = null; try { URL aURL = new URL(url); URLConnection conn = aURL.openConnection(); conn.connect(); InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bm = BitmapFactory.decodeStream(bis); bis.close(); is.close(); } catch (IOException e) { Log.e("Hub","Error getting the image from server : " + e.getMessage().toString()); } return bm; //--------------------------------------------------- } } 

pero ¿cómo paso una referencia a mChart en onPostExecute (resultado de bitmap)? ¿Debo pasarlo con la URL de alguna manera? Me gustaría reemplazar todas mis líneas de código:

 mChart1.setImageBitmap(download_Image(URL_1)); mChart2.setImageBitmap(download_Image(URL_2)); 

con algo similar … ¡pero a la manera de Asynctask!

 mChart1.setImageBitmap(new DownloadImagesTask().execute(graph_URL_1)); mChart2.setImageBitmap(new DownloadImagesTask().execute(graph_URL_2)); 

¿Hay una solución fácil para esto? ¿Me sale algo mal aquí?

Si no hay una buena razón para descargar la imagen usted mismo, le recomendaría usar Picasso .

Picasso le ahorra todos los problemas con la descarga, configuración y almacenamiento en caché de imágenes. Todo el código necesario para un ejemplo simple es:

 Picasso.with(context).load(url).into(imageView); 

Si realmente quieres hacer todo tú mismo, utiliza mi respuesta anterior a continuación.


Si la imagen no es tan grande, puedes usar una clase anónima para la tarea asincrónica. Esto me gustaría esto:

 ImageView mChart = (ImageView) findViewById(R.id.imageview); String URL = "http://www...anything ..."; mChart.setTag(URL); new DownloadImageTask.execute(mChart); 

La clase de tarea:

 public class DownloadImagesTask extends AsyncTask { ImageView imageView = null; @Override protected Bitmap doInBackground(ImageView... imageViews) { this.imageView = imageViews[0]; return download_Image((String)imageView.getTag()); } @Override protected void onPostExecute(Bitmap result) { imageView.setImageBitmap(result); } private Bitmap download_Image(String url) { ... } 

Ocultar la URL en la etiqueta es un poco complicado, pero se ve mejor en la clase de llamada si tiene muchas imágenes que desea llenar de esta manera. También ayuda si está utilizando ImageView dentro de un ListView y desea saber si el ImageView se recicló durante la descarga de la imagen.

Escribí si la imagen no es tan grande porque dará como resultado que la tarea tenga un puntero implícito a la actividad subyacente que hace que el recolector de basura mantenga toda la actividad en la memoria hasta que la tarea finalice. Si el usuario se mueve a otra pantalla de su aplicación mientras se descarga el bitmap, la memoria no se puede liberar y puede hacer que su aplicación y todo el sistema disminuyan.

Prueba este código:

 ImageView myFirstImage = (ImageView) findViewById(R.id.myFirstImage); ImageView mySecondImage = (ImageView) findViewById(R.id.mySecondImage); ImageView myThirdImage = (ImageView) findViewById(R.id.myThirdImage); String URL1 = "http://sofes.miximages.com/android/estonia_independence_day_2013-1057005.3-hp.jpg"; String URL2 = "http://sofes.miximages.com/android/park_su-geuns_birthday-1055005-hp.jpg"; String URL3 = "http://sofes.miximages.com/android/anne_cath_vestlys_93rd_birthday-1035005-hp.jpg"; myFirstImage.setTag(URL1); mySecondImage.setTag(URL2); myThirdImage.setTag(URL3); new DownloadImageTask.execute(myFirstImage); new DownloadImageTask.execute(mySecondImage); new DownloadImageTask.execute(myThirdImage); public class DownloadImagesTask extends AsyncTask { ImageView imageView = null; @Override protected Bitmap doInBackground(ImageView... imageViews) { this.imageView = imageViews[0]; return download_Image((String)imageView.getTag()); } @Override protected void onPostExecute(Bitmap result) { imageView.setImageBitmap(result); } private Bitmap download_Image(String url) { Bitmap bmp =null; try{ URL ulrn = new URL(url); HttpURLConnection con = (HttpURLConnection)ulrn.openConnection(); InputStream is = con.getInputStream(); bmp = BitmapFactory.decodeStream(is); if (null != bmp) return bmp; }catch(Exception e){} return bmp; } } 

puedes crear una clase say..BkgProcess que contenga una clase interna que amplíe AsyncTask. al instanciar BkgProcess, pasa el contexto de tu clase de actividad en BkgProcess constructor. por ejemplo:

 public class BkgProcess { String path; Context _context; public Download(Downloader downloader, String path2){ this.path = path2; _context = downloader; } public void callProgressDialog(){ new BkgProcess().execute((Void)null); } class Downloads extends AsyncTask { private ProgressDialog dialog = new ProgressDialog(_context); protected void onPreExecute(){ dialog.setMessage("Downloading image.."); dialog.show(); } protected void onPostExecute(Boolean success) { dialog.dismiss(); if(success) Toast.makeText(_context, "Download complete", Toast.LENGTH_SHORT).show(); } @Override protected Boolean doInBackground(Void... params) { return(startDownload(path)); } public boolean startDownload(String img_url) { // download img.. return true; } } } 

de tu clase de actividad …

 BkgProcess dwn = new BkgProcess (Your_Activity_class.this, img_path); dwn.callProgressDialog(); 

Esto te dará imágenes de cualquier tamaño … si no quieres el diálogo de progreso solo comenta los códigos en onPreExecute ();

 for(int i = 0 ; i < no_of_files ; i++ ) new FetchFilesTask().execute(image_url[i]); private class FetchFilesTask extends AsyncTask { private ProgressDialog dialog = new ProgressDialog(FileExplorer.this); Bitmap bitmap[]; protected void onPreExecute(){ dialog.setMessage("fetching image from the server"); dialog.show(); } protected Bitmap doInBackground(String... args) { bitmap = getBitmapImageFromServer(); return bitmap; } protected void onPostExecute(Bitmap m_bitmap) { dialog.dismiss(); if(m_bitmap != null) //store the images in an array or do something else with all the images. } } public Bitmap getBitmapImageFromServer(){ // fetch image form the url using the URL and URLConnection class }