Android:使用 Asynctask 从 Web 加载图像
Posted
技术标签:
【中文标题】Android:使用 Asynctask 从 Web 加载图像【英文标题】:Android : Loading an image from the Web with Asynctask 【发布时间】:2011-03-06 15:52:03 【问题描述】:如何用 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;
//---------------------------------------------------
我想过这样的事情:
替换:
mChart.setImageBitmap(download_Image(graph_URL));
类似:
mChart.setImageBitmap(new DownloadImagesTask().execute(graph_URL));
和
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;
//---------------------------------------------------
但是如何在 onPostExecute(Bitmap result) 中传递对 mChart 的引用? 我是否需要以某种方式将其与 URL 一起传递? 我想替换我所有的代码行:
mChart1.setImageBitmap(download_Image(URL_1));
mChart2.setImageBitmap(download_Image(URL_2));
使用类似的东西......但以 Asynctask 方式!
mChart1.setImageBitmap(new DownloadImagesTask().execute(graph_URL_1));
mChart2.setImageBitmap(new DownloadImagesTask().execute(graph_URL_2));
有没有简单的解决方案? 我这里有什么问题吗?
【问题讨论】:
非常基本的问题,但我认为对像我这样的初学者很有用......如果有的话,请发布一些代码。 相关:ImageDownloader example @Hubert 能否请您提及 private Bitmap download_Image(String url) ... 这段代码? 如果您使用 Glide 和 Kotlin,那么this 可以帮助您。 【参考方案1】:如果没有充分的理由自己下载图像,那么我建议使用Picasso。
Picasso 为您省去了下载、设置和缓存图像的所有问题。 一个简单示例所需的整个代码是:
Picasso.with(context).load(url).into(imageView);
如果您真的想自己做所有事情,请使用下面我的旧答案。
如果图像不是那么大,您可以使用匿名类来执行异步任务。 这会是这样的:
ImageView mChart = (ImageView) findViewById(R.id.imageview);
String URL = "http://www...anything ...";
mChart.setTag(URL);
new DownloadImageTask.execute(mChart);
任务类:
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)
...
在标签中隐藏 URL 有点棘手,但如果您有很多要以这种方式填充的图像视图,它在调用类中看起来会更好。如果您在 ListView 中使用 ImageView 并且您想知道 ImageView 在下载图像期间是否被回收,这也会有所帮助。
我写了如果你的图像不是那么大,因为这将导致任务具有指向底层活动的隐式指针,导致垃圾收集器将整个活动保存在内存中,直到任务完成。如果用户在下载位图时移动到应用程序的另一个屏幕,则无法释放内存,这可能会使您的应用程序和整个系统变慢。
【讨论】:
我的图像类似于 45.2 Ko (46,384 八位字节) gif 类型,如果这有什么不同吗? 这只是一个问题,如果它需要更长的时间,然后我猜想 20 秒来下载图像并且您的活动对系统内存很重要。 谢谢 Janusz,我对我的问题进行了编辑,并添加了一些内容。你怎么看 ?事实上,我想在不同的 ImageViews 上使用这个 AsyncTask。如何在 onPostExecute 中传递对 ImageView 的正确引用?非常感谢您的帮助。 你不能这样做:mChart1.setImageBitmap(new DownloadImagesTask().execute(graph_URL_1));因为异步任务不能返回一些东西。返回意味着在任务准备好之前阻止执行,但您不想这样做。 看看我的回答就知道了。标签的使用会让调用类看起来更干净一些【参考方案2】:试试这个代码:
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;
【讨论】:
return download_Image((String)imageView.getTag());
给出错误。 getTag must be called from the UI thread
我在位图中得到一个空结果,即使我在浏览器中点击 URL,我也会收到图像。你能说出为什么会这样吗?
用法必须是这样的:new DownloadImageTask().execute(myFirstImage);新的 DownloadImageTask().execute(mySecondImage); new DownloadImageTask().execute(myThirdImage);【参考方案3】:
您可以创建一个类 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;
来自你的活动课..
BkgProcess dwn = new BkgProcess (Your_Activity_class.this, img_path);
dwn.callProgressDialog();
【讨论】:
【参考方案4】:这将为您提供任何尺寸的图像... 如果您不想要进度对话框,只需在 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
【讨论】:
感谢 Umesh 的提议。也许确实我还应该添加一个 ProgressDialog,以防万一!但是你如何将上下文(你的 FileExplorer.this)传递给 AsyncTask 呢???我希望我的 DownloadImagesTask() 可以从我的应用程序的任何活动中访问......我为它创建了一个单独的类。以上是关于Android:使用 Asynctask 从 Web 加载图像的主要内容,如果未能解决你的问题,请参考以下文章
在 android studio 中使用 AsyncTask 从套接字读取数据
如何使用 asynctask 将图像从 android 上传到 php
Android - 将数据从 AsyncTask 传递到 Activity
在 Android 中,如何从 AsyncTask 更改 TextView? [复制]