Android:使用 Asynctask 从 Web 加载图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3090650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:39:20  来源:igfitidea点击:

Android : Loading an image from the Web with Asynctask

androidandroid-asynctask

提问by Hubert

How do I replace the following lines of code with an Asynctask ? How do you "get back" the Bitmap from the Asynctask ? Thank you.

如何用 Asynctask 替换以下代码行?你如何从 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;
        //---------------------------------------------------

    }

I thought about something like this :

我想过这样的事情:

replace :

代替 :

mChart.setImageBitmap(download_Image(graph_URL));

by something like :

通过类似的东西:

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

and

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


}

but How do I pass a reference to mChart in onPostExecute(Bitmap result) ??? Do I need to pass it with the URL in some way ? I would like to replace all my lines of code :

但是如何在 onPostExecute(Bitmap result) 中传递对 mChart 的引用???我需要以某种方式通过 URL 传递它吗?我想替换我所有的代码行:

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

with something similar ... but in Asynctask way !

与类似的东西......但在Asynctask方式!

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

Is there an easy solution for this ? Do I get something wrong here ?

有没有一个简单的解决方案?我这里有什么问题吗?

回答by Janusz

If there is no good reason to download the image yourself then I would recommend to use Picasso.

如果没有充分的理由自己下载图像,那么我建议使用Picasso

Picasso saves you all the problems with downloading, setting and caching images. The whole code needed for a simple example is:

Picasso 为您节省了下载、设置和缓存图像的所有问题。一个简单示例所需的整个代码是:

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

If you really want to do everything yourself use my older answer below.

如果您真的想自己做所有事情,请使用我下面的旧答案。



If the image is not that big you can just use an anonymous class for the async task. This would like this:

如果图像不是那么大,您可以使用匿名类进行异步任务。这会是这样的:

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

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

The Task class:

任务类:

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

Hiding the URL in the tag is a bit tricky but it looks nicer in the calling class if you have a lot of imageviews that you want to fill this way. It also helps if you are using the ImageView inside a ListView and you want to know if the ImageView was recycled during the download of the image.

在标签中隐藏 URL 有点棘手,但如果你有很多想要以这种方式填充的图像视图,它在调用类中看起来会更好。如果您在 ListView 中使用 ImageView 并且您想知道 ImageView 在下载图像期间是否被回收,这也有帮助。

I wrote if you Image is not that big because this will result in the task having a implicit pointer to the underlying activity causing the garbage collector to hold the whole activity in memory until the task is finished. If the user moves to another screen of your app while the bitmap is downloading the memory can't be freed and it may make your app and the whole system slower.

我写道,如果您的图像不是那么大,因为这将导致任务具有指向底层活动的隐式指针,从而导致垃圾收集器将整个活动保存在内存中,直到任务完成。如果用户在位图下载时移动到应用程序的另一个屏幕,则无法释放内存,这可能会使您的应用程序和整个系统变慢。

回答by AboZeid

Try this 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;
    }
}

回答by Umesh

you can create a class say..BkgProcess which contains an inner class that extends AsyncTask. while instantiating BkgProcess pass the context of your Activity class in BkgProcess constructor. for eg:

您可以创建一个类 say..BkgProcess ,其中包含一个扩展 AsyncTask 的内部类。在实例化 BkgProcess 时,在 BkgProcess 构造函数中传递 Activity 类的上下文。例如:

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

from your activity class..

从你的活动课..

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

dwn.callProgressDialog();

回答by Umesh

This will get you images of any size... if you dont want the progress dialog just comment the codes in onPreExecute();

这将为您提供任何大小的图像...如果您不想要进度对话框,只需注释 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
}