很多时候我们需要在Android设备上下载远程服务器上的图片进行显示,今天eoeAndroid整理出两种比较好的方法来实现远程图片的下载。

       方法一、直接通过Android提供的Http类访问远程服务器,这里AndroidHttpClient是SDK 2.2中新出的方法,API Level为8,大家需要注意下,静态访问可以直接调用,如果SDK版本较低可以考虑Apache的Http库,当然HttpURLConnection 或URLConnection也可以。

Java代码:

  1. static Bitmap downloadBitmapByCwj(String url) {
  2. final AndroidHttpClient client = AndroidHttpClient.newInstance("Android123");
  3. final HttpGet getRequest = new HttpGet(url);
  4. try {
  5. HttpResponse response = client.execute(getRequest);
  6. final int statusCode = response.getStatusLine().getStatusCode();
  7. if (statusCode != HttpStatus.SC_OK) {
  8. Log.e("cwjDebug", "Error " + statusCode + " while retrieving bitmap from " + url);
  9. return null;
  10. }
  11. final HttpEntity entity = response.getEntity();
  12. if (entity != null) {
  13. InputStream inputStream = null;
  14. try {
  15. inputStream = entity.getContent();
  16. final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
  17. return bitmap;
  18. } finally {
  19. if (inputStream != null) {
  20. inputStream.close();
  21. }
  22. entity.consumeContent();
  23. }
  24. }
  25. } catch (Exception e) {
  26. getRequest.abort();
  27. Log.e("android123Debug", "Error while retrieving bitmap from " + url, e.toString());
  28. } finally {
  29. if (client != null) {
  30. client.close();
  31. }
  32. }
  33. return null;
  34. }
复制代码


       这里eoeAndroid提醒大家,BitmapFactory类的decodeStream方法在网络超时或较慢的时候无法获取完整的数据,这里我们通 过继承FilterInputStream类的skip方法来强制实现flush流中的数据,主要原理就是检查是否到文件末端,告诉http类是否继续。

Java代码:

  1. static class FlushedInputStream extends FilterInputStream {
  2. public FlushedInputStream(InputStream inputStream) {
  3. super(inputStream);
  4. }
  5. @Override
  6. public long skip(long n) throws IOException {
  7. long totalBytesSkipped = 0L;
  8. while (totalBytesSkipped < n) {
  9. long bytesSkipped = in.skip(n - totalBytesSkipped);
  10. if (bytesSkipped == 0L) {
  11. int byte = read();
  12. if (byte < 0) {
  13. break;
  14. } else {
  15. bytesSkipped = 1;
  16. }
  17. }
  18. totalBytesSkipped += bytesSkipped;
  19. }
  20. return totalBytesSkipped;
  21. }
  22. }
复制代码


       方法二、AsyncTask异步任务

       从Android 1.5固件开始Google提供了一个AsyncTask类来帮助开发者处理异步下载的实现,相对于Thread而言他可以运行在UI线程中,其内部的实 现是从Java 5开始的并发包concurrent中派生而来的,总体实现比较可靠就是资源占用略大了些。不过使用起来比简单。这里下载图片类 ImageDownloader类的download方法可以很好的处理实现UI显示等操作,参数一url为远程server上文件的url,第二个参数 为imageview对象,可以直接让imageview显示出下载的远程图片。

Java代码:

  1. public class ImageDownloader {
  2. public void download(String url, ImageView imageView) {
  3. BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
  4. task.execute(url);
  5. }
  6. }
  7. }
复制代码


Java代码:

  1. class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
  2. private String url;
  3. private final WeakReference<ImageView> imageViewReference; //使用WeakReference解决内存问题
  4. public BitmapDownloaderTask(ImageView imageView) {
  5. imageViewReference = new WeakReference<ImageView>(imageView);
  6. }
  7. @Override
  8. protected Bitmap doInBackground(String... params) { //实际的下载线程,内部其实是concurrent线程,所以不会阻塞
  9. return downloadBitmap(params[0]);
  10. }
  11. @Override
  12. protected void onPostExecute(Bitmap bitmap) { //下载完后执行的
  13. if (isCancelled()) {
  14. bitmap = null;
  15. }
  16. if (imageViewReference != null) {
  17. ImageView imageView = imageViewReference.get();
  18. if (imageView != null) {
  19. imageView.setImageBitmap(bitmap); //下载完设置imageview为刚才下载的bitmap对象
  20. }
  21. }
  22. }
  23. }
复制代码