2010-06-22 18 views
31

¿Cómo reemplazo las siguientes líneas de código con Asynctask? ¿Cómo "recuperas" el mapa de bits de Asynctask? Gracias.Android: cargando una imagen desde la Web con Asynctask

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<String, Void, Bitmap> { 

@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 mapa de bits) ??? ¿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 parecido ... pero en forma AsyncTask!

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

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

+0

pregunta bastante básica, pero sería útil para muchos principiantes como yo creo ... por favor publique un código si lo tiene. – Hubert

+0

Relacionado: el [ejemplo de ImageDownloader] (http://developer.android.com/resources/samples/XmlAdapters/src/com/example/android/xmladapters/ImageDownloader.html) – idbrii

+0

@Hubert puede mencionar el mapa de bits privado download_Image (String url) { ... } este código? – Erum

Respuesta

65

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, el ajuste y el almacenamiento en caché de imágenes. Todo el código necesario para un ejemplo sencillo es:

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

Si realmente quiere hacer todo usted mismo utiliza mi respuesta Mayor continuación.


Si la imagen no es tan grande, puede utilizar una clase anónima para la tarea asíncrona. Esto lo desea:

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

mChart.setTag(URL); 
new DownloadImageTask.execute(mChart); 

La clase de tareas:

public class DownloadImagesTask extends AsyncTask<ImageView, Void, Bitmap> { 

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 dirección URL en la etiqueta es un poco complicado pero se ve mejor en la clase de llamada si usted tiene una gran cantidad de imageviews que quieres 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 retenga 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 mapa de bits, la memoria no se puede liberar y puede hacer que su aplicación y todo el sistema disminuyan.

+0

mis imágenes son algo así como 45,2 Ko (46,384 octets) tipo de gif, si eso hace alguna diferencia? – Hubert

+0

solo es un problema si lleva más tiempo, supongo que 20 segundos para descargar las imágenes y su actividad es pesada en la memoria del sistema. – Janusz

+0

Gracias Janusz, hice un EDIT de mi pregunta con algunas cosas adicionales. Qué piensas ? Me gustaría utilizar este AsyncTask en diferentes ImageViews de hecho. ¿Cómo paso la referencia correcta a ImageView en onPostExecute? Muchas gracias por su ayuda. – Hubert

0

Esto le dará imágenes de cualquier tamaño ... si no desea el diálogo de progreso simplemente comente 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<String, Void, Bitmap> { 

    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 
} 
+1

Gracias Umesh por su proposición. Tal vez, de hecho, también debería agregar un ProgressDialog, ¡por las dudas! ¿Pero cómo pasaría el contexto (su FileExplorer.this) al AsyncTask entonces ??? Me gustaría que se pueda acceder a mi DownloadImagesTask() desde cualquier actividad de mi aplicación ... Creé una clase separada para ella. – Hubert

1

puede crear un say..BkgProcess clase que contiene una clase interna que se extiende 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<Void, Void, Boolean> { 
    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 su clase de actividad ..

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

dwn.callProgressDialog(); 
18

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://www.google.com/logos/2013/estonia_independence_day_2013-1057005.3-hp.jpg"; 
String URL2 = "http://www.google.com/logos/2013/park_su-geuns_birthday-1055005-hp.jpg"; 
String URL3 = "http://www.google.com/logos/2013/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, Void, Bitmap> { 

    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; 
    } 
} 
+0

'return download_Image ((String) imageView.getTag());' da error. 'getTag debe invocarse desde el hilo de UI' – XoXo

Cuestiones relacionadas