web-dev-qa-db-fra.com

Android: Chargement d'une image à partir du Web avec Asynctask

Comment remplacer les lignes de code suivantes par un Asynctask? Comment "récupérez-vous" le bitmap de la tâche Asynctask? Merci.

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

    }

J'ai pensé à quelque chose comme ça:

remplacer:

mChart.setImageBitmap(download_Image(graph_URL));

par quelque chose comme:

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

et

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


}

mais comment passer une référence à mChart dans onPostExecute (résultat Bitmap) ??? Dois-je le transmettre avec l'URL d'une manière ou d'une autre? Je voudrais remplacer toutes mes lignes de code:

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

avec quelque chose de similaire ... mais à la manière d'Asynctask!

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

Existe-t-il une solution simple à cela? Est-ce que je me trompe ici?

36
Hubert

S'il n'y a pas de bonne raison de télécharger l'image vous-même, je recommanderais d'utiliser Picasso .

Picasso vous évite tous les problèmes de téléchargement, de configuration et de mise en cache des images. Le code complet nécessaire pour un exemple simple est:

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

Si vous voulez vraiment tout faire vous-même, utilisez mon ancienne réponse ci-dessous.


Si l'image n'est pas si grande, vous pouvez simplement utiliser une classe anonyme pour la tâche asynchrone. Cela voudrait ceci:

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

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

La classe Task:

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) {
   ...
}

Masquer l'URL dans la balise est un peu délicat mais cela semble plus agréable dans la classe appelante si vous avez beaucoup de vues d'images que vous souhaitez remplir de cette façon. Cela aide également si vous utilisez ImageView dans un ListView et que vous souhaitez savoir si ImageView a été recyclé lors du téléchargement de l'image.

J'ai écrit si votre image n'est pas si grande car cela entraînera un pointeur implicite vers l'activité sous-jacente, obligeant le garbage collector à conserver toute l'activité en mémoire jusqu'à la fin de la tâche. Si l'utilisateur passe à un autre écran de votre application pendant que le bitmap télécharge, la mémoire ne peut pas être libérée et cela peut ralentir votre application et l'ensemble du système.

74
Janusz

Essayez ce code:

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;
    }
}
23
AboZeid

vous pouvez créer une classe say..BkgProcess qui contient une classe interne qui étend AsyncTask. lors de l'instanciation de BkgProcess, passez le contexte de votre classe Activity dans le constructeur BkgProcess. par exemple:

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 votre classe d'activité ..

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

dwn.callProgressDialog();
2
Umesh

Cela vous donnera des images de n'importe quelle taille ... si vous ne voulez pas que la boîte de dialogue de progression commente simplement les codes dans 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
Umesh