在ListView中延迟加载图像

我正在使用ListView来显示与这些图像相关的一些图像和标题。 我正在从互联网上获取图像。 有没有办法延迟加载图像,所以当文本显示,用户界面没有locking,图像显示为他们下载?

图像总数不固定。

这是我创build的,以保存我的应用程序当前显示的图像。 请注意,这里使用的“Log”对象是我在Android内部的最终Log类中的自定义包装。

 package com.wilson.android.library; /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import java.io.IOException; public class DrawableManager { private final Map<String, Drawable> drawableMap; public DrawableManager() { drawableMap = new HashMap<String, Drawable>(); } public Drawable fetchDrawable(String urlString) { if (drawableMap.containsKey(urlString)) { return drawableMap.get(urlString); } Log.d(this.getClass().getSimpleName(), "image url:" + urlString); try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); if (drawable != null) { drawableMap.put(urlString, drawable); Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", " + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", " + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth()); } else { Log.w(this.getClass().getSimpleName(), "could not get thumbnail"); } return drawable; } catch (MalformedURLException e) { Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } catch (IOException e) { Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } } public void fetchDrawableOnThread(final String urlString, final ImageView imageView) { if (drawableMap.containsKey(urlString)) { imageView.setImageDrawable(drawableMap.get(urlString)); } final Handler handler = new Handler() { @Override public void handleMessage(Message message) { imageView.setImageDrawable((Drawable) message.obj); } }; Thread thread = new Thread() { @Override public void run() { //TODO : set imageView to a "pending" image Drawable drawable = fetchDrawable(urlString); Message message = handler.obtainMessage(1, drawable); handler.sendMessage(message); } }; thread.start(); } private InputStream fetch(String urlString) throws MalformedURLException, IOException { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpGet request = new HttpGet(urlString); HttpResponse response = httpClient.execute(request); return response.getEntity().getContent(); } } 

我用图像做了一个懒惰列表 (位于GitHub) 的简单演示 。 有人可能会有所帮助。 它在后台线程中下载图像。 图像被caching在SD卡和内存中。 高速caching的实现非常简单,对于演示就足够了。 我用inSampleSize解码图像以减less内存消耗。 我也尝试正确处理再循环视图。

替代文字

我推荐开源的仪器Universal Image Loader 。 它最初是基于Fedor Vlasov的LazyList项目,自那时以来得到了极大的改善。

  • multithreading图像加载
  • 广泛调整ImageLoader的configuration(线程执行者,下载器,解码器,内存和磁盘caching,显示图像选项等)的可能性
  • 在内存和/或设备的文件系统(或SD卡)上进行图像caching的可能性
  • 可以“听”加载过程
  • 可以使用单独的选项自定义每个显示图像调用
  • 小部件支持
  • Android 2.0+支持

multithreading对于性能 ,Gilles Debunne的教程。

这是来自Android开发者博客。 build议的代码使用:

  • AsyncTasks
  • 一个硬的有限大小的FIFO cache
  • 一个软,容易garbage collectcaching。
  • 占位符在下载时Drawable

在这里输入图像描述

更新:请注意,这个答案现在是相当无效的。 垃圾收集器在SoftReference和WeakReference上积极行事,所以这个代码不适合新的应用程序。 (而是尝试其他答案中提到的通用图像加载程序等库)。

感谢James提供的代码,而宝龙提供了使用SoftReference的build议。 我在James的代码上实现了SoftReference的改变。 不幸的是,SoftReferences导致我的图像被垃圾收集太快。 在我的情况下,没有SoftReference的东西没有问题,因为我的列表大小是有限的,我的图片很小。

一年前有一个讨论谷歌组的SoftReferences: 链接到线程 。 作为过早垃圾回收的解决scheme,他们build议使用dalvik.system.VMRuntime.setMinimumHeapSize()手动设置VM堆大小,这对我来说不是很有吸引力。

 public DrawableManager() { drawableMap = new HashMap<String, SoftReference<Drawable>>(); } public Drawable fetchDrawable(String urlString) { SoftReference<Drawable> drawableRef = drawableMap.get(urlString); if (drawableRef != null) { Drawable drawable = drawableRef.get(); if (drawable != null) return drawable; // Reference has expired so remove the key from drawableMap drawableMap.remove(urlString); } if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString); try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); drawableRef = new SoftReference<Drawable>(drawable); drawableMap.put(urlString, drawableRef); if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", " + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", " + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth()); return drawableRef.get(); } catch (MalformedURLException e) { if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } catch (IOException e) { if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e); return null; } } public void fetchDrawableOnThread(final String urlString, final ImageView imageView) { SoftReference<Drawable> drawableRef = drawableMap.get(urlString); if (drawableRef != null) { Drawable drawable = drawableRef.get(); if (drawable != null) { imageView.setImageDrawable(drawableRef.get()); return; } // Reference has expired so remove the key from drawableMap drawableMap.remove(urlString); } final Handler handler = new Handler() { @Override public void handleMessage(Message message) { imageView.setImageDrawable((Drawable) message.obj); } }; Thread thread = new Thread() { @Override public void run() { //TODO : set imageView to a "pending" image Drawable drawable = fetchDrawable(urlString); Message message = handler.obtainMessage(1, drawable); handler.sendMessage(message); } }; thread.start(); } 

毕加索

使用杰克·沃顿的毕加索图书馆。 (完美的ImageLoading库是ActionBarSherlock的开发者)

一个强大的图像下载和Android的caching库。

图像为Android应用程序添加了非常需要的上下文和视觉天赋。 毕加索允许在应用程序中轻松加载图像 – 通常只需一行代码!

 Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); 

Android上图片加载的许多常见陷阱都是由毕加索自动处理的:

处理ImageView回收并在适配器中下载取消。 复杂的图像转换与最小的内存使用。 自动内存和磁盘caching。

毕加索杰克·沃顿的图书馆

滑行

Glide是一个快速高效的Android开源媒体pipe理框架,将媒体解码,内存和磁盘caching以及资源池整合到一个简单易用的界面中。

Glide支持获取,解码和显示video静止图像,图像和animationGIF。 Glide包括一个灵活的API,允许开发人员插入几乎任何networking堆栈。 默认情况下,Glide使用基于自定义HttpUrlConnection的堆栈,但也包括实用程序库插入到Google的Volley项目或Square的OkHttp库中。

 Glide.with(this).load("http://goo.gl/h8qOq7").into(imageView); 

Glide的主要焦点是尽可能平滑和快速地滚动任何types的图像列表,但对于几乎任何需要获取,resize和显示远程图像的情况,Glide都是有效的。

滑动图像加载库

Facebook的壁画

壁画是在Android应用程序中显示图像的强大系统。

壁画照顾图像加载和显示,所以你不必。 它将从networking,本地存储或本地资源加载图像,并在图像到达之前显示一个占位符。 它有两个级别的caching; 一个在内存中,另一个在内部存储器中。

壁画Github

在Android 4.x及更低版本中,Fresco将图像放在Android内存的特殊区域。 这可以让你的应用程序运行得更快 – 并且让恐惧的OutOfMemoryError更加频繁。

壁画文件

高性能的加载程序 – 在检查了这里build议的方法之后,我用Ben的解决scheme进行了一些修改 –

  1. 我意识到使用drawables的速度更快,所以我使用drawable来代替

  2. 使用SoftReference非常好,但它使得caching的图像被删除得太频繁,所以我添加了一个保存图像引用的链接列表,防止图像被删除,直到达到预定义的大小

  3. 要打开InputStream,我使用了java.net.URLConnection,它允许我使用Webcaching(首先需要设置响应caching,但这是另一回事)

我的代码:

 import java.util.Map; import java.util.HashMap; import java.util.LinkedList; import java.util.Collections; import java.util.WeakHashMap; import java.lang.ref.SoftReference; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import android.graphics.drawable.Drawable; import android.widget.ImageView; import android.os.Handler; import android.os.Message; import java.io.InputStream; import java.net.MalformedURLException; import java.io.IOException; import java.net.URL; import java.net.URLConnection; public class DrawableBackgroundDownloader { private final Map<String, SoftReference<Drawable>> mCache = new HashMap<String, SoftReference<Drawable>>(); private final LinkedList <Drawable> mChacheController = new LinkedList <Drawable> (); private ExecutorService mThreadPool; private final Map<ImageView, String> mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); public static int MAX_CACHE_SIZE = 80; public int THREAD_POOL_SIZE = 3; /** * Constructor */ public DrawableBackgroundDownloader() { mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); } /** * Clears all instance data and stops running threads */ public void Reset() { ExecutorService oldThreadPool = mThreadPool; mThreadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); oldThreadPool.shutdownNow(); mChacheController.clear(); mCache.clear(); mImageViews.clear(); } public void loadDrawable(final String url, final ImageView imageView,Drawable placeholder) { mImageViews.put(imageView, url); Drawable drawable = getDrawableFromCache(url); // check in UI thread, so no concurrency issues if (drawable != null) { //Log.d(null, "Item loaded from mCache: " + url); imageView.setImageDrawable(drawable); } else { imageView.setImageDrawable(placeholder); queueJob(url, imageView, placeholder); } } private Drawable getDrawableFromCache(String url) { if (mCache.containsKey(url)) { return mCache.get(url).get(); } return null; } private synchronized void putDrawableInCache(String url,Drawable drawable) { int chacheControllerSize = mChacheController.size(); if (chacheControllerSize > MAX_CACHE_SIZE) mChacheController.subList(0, MAX_CACHE_SIZE/2).clear(); mChacheController.addLast(drawable); mCache.put(url, new SoftReference<Drawable>(drawable)); } private void queueJob(final String url, final ImageView imageView,final Drawable placeholder) { /* Create handler in UI thread. */ final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String tag = mImageViews.get(imageView); if (tag != null && tag.equals(url)) { if (imageView.isShown()) if (msg.obj != null) { imageView.setImageDrawable((Drawable) msg.obj); } else { imageView.setImageDrawable(placeholder); //Log.d(null, "fail " + url); } } } }; mThreadPool.submit(new Runnable() { @Override public void run() { final Drawable bmp = downloadDrawable(url); // if the view is not visible anymore, the image will be ready for next time in cache if (imageView.isShown()) { Message message = Message.obtain(); message.obj = bmp; //Log.d(null, "Item downloaded: " + url); handler.sendMessage(message); } } }); } private Drawable downloadDrawable(String url) { try { InputStream is = getInputStream(url); Drawable drawable = Drawable.createFromStream(is, url); putDrawableInCache(url,drawable); return drawable; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private InputStream getInputStream(String urlString) throws MalformedURLException, IOException { URL url = new URL(urlString); URLConnection connection; connection = url.openConnection(); connection.setUseCaches(true); connection.connect(); InputStream response = connection.getInputStream(); return response; } } 

我遵循这个Android培训,我认为它在下载图像方面做得非常出色,并且不会阻塞主UI。 它还处理caching和处理滚动许多图像: 高效地加载大的位图

我写了一个教程,解释如何在列表视图中执行延迟加载的图像。 我详细讨论了回收和并发的问题。 我也使用一个固定的线程池来防止产生大量的线程。

Listview教程中的图像延迟加载

1. 毕加索允许在应用程序中轻松加载图像 – 通常只需一行代码即可!

使用Gradle:

 compile 'com.squareup.picasso:picasso:2.5.2' 

只需一行代码!

 Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); 

Android上图像加载的许多常见陷阱都是由毕加索自动处理的

  • 处理ImageView回收并在适配器中下载取消。
  • 复杂的图像转换与最小的内存使用。
  • 自动内存和磁盘caching。

在这里输入图像描述

2. 滑翔 Android的图像加载和caching库专注于平滑滚动

使用Gradle:

 repositories { mavenCentral() // jcenter() works as well because it pulls from Maven Central } dependencies { compile 'com.github.bumptech.glide:glide:3.7.0' compile 'com.android.support:support-v4:19.1.0' } 

//对于一个简单的视图:

 @Override public void onCreate(Bundle savedInstanceState) { ... ImageView imageView = (ImageView) findViewById(R.id.my_image_view); Glide.with(this).load("http://i.imgur.com/DvpvklR.png").into(imageView); } 

//对于一个简单的图片列表:

  @Override public View getView(int position, View recycled, ViewGroup container) { final ImageView myImageView; if (recycled == null) { myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false); } else { myImageView = (ImageView) recycled; } String url = myUrls.get(position); Glide .with(myFragment) .load(url) .centerCrop() .placeholder(R.drawable.loading_spinner) .crossFade() .into(myImageView); return myImageView; } 

我这样做的方式是启动一个线程在后台下载图像,并为每个列表项目交回一个callback。 当图像完成下载时,它会调用更新列表项视图的callback函数。

但是,当您回收视图时,此方法效果不佳。

我只想添加一个很好的例子, XML适配器 。 因为它被Google使用,我也使用相同的逻辑来避免OutOfMemory错误。

基本上这个ImageDownloader是你的答案(因为它涵盖了你的大部分要求)。 有些你也可以在那里实现。

我一直在使用新的Android Volley库com.android.volley.toolbox.NetworkImageView NetworkImageView,它似乎工作得很好。 显然,这与Google Play和其他新的Google应用程序所使用的观点相同。 绝对值得一试。

  • Google I / O 2013排球图像caching教程

  • 开发者Google活动

这是Android上的一个常见问题,已经被很多人解决了。 在我看来,我所见过的最好的解决scheme是名为毕加索的相对较新的图书馆。 以下是亮点:

  • 开源,但由ActionBarSherlock成名的Jake Wharton领导。
  • 使用一行代码asynchronous加载来自networking或应用程序资源的图像
  • 自动ListView检测
  • 自动磁盘和内存caching
  • 可以做自定义转换
  • 许多可configuration的选项
  • 超级简单的API
  • 经常更新

我认为这个问题在Android开发者中非常stream行,有很多这样的库声称可以解决这个问题,但是其中只有less数似乎是标记的。 AQuery就是这样一个库,但是它比其中的大多数都好,值得一试。

那么,从互联网的图像加载时间有很多解决scheme。 您也可以使用Android-Query库。 它会给你所有需要的活动。 确保你想要做什么,阅读图书馆的维基页面。 并解决图片加载限制。

这是我的代码:

 @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.row, null); } ImageView imageview = (ImageView) v.findViewById(R.id.icon); AQuery aq = new AQuery(convertView); String imageUrl = "http://www.vikispot.com/zhttp://img.dovov.comvikispot/android-w.png"; aq.id(imageview).progress(this).image(imageUrl, true, true, 0, 0, new BitmapAjaxCallback() { @Override public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) { iv.setImageBitmap(bm); } )); return v; } 

这应该是解决你的懒加载问题。

看看Shutterbug ,Applidium的轻量级SDWebImage(iOS上的一个很好的库)的端口到Android。 它支持asynchronouscaching,存储失败的URL,很好地处理并发,并包含有用的子类。

拉请求(和错误报告)也是受欢迎的!

Novoda也有一个非常漂亮的图片加载库 ,很多像Songkick,Podio,SecretDJ和ImageSearch的应用都使用他们的库。

他们的图书馆在Github上托pipe,他们也有一个非常活跃的问题追踪器 。 他们的项目似乎也非常活跃,在撰写本答复时有300多个提交。

DroidParts有ImageFetcher ,需要零configuration才能入门。

  • 使用磁盘和内存最近最less使用 (LRU)caching。
  • 有效解码图像。
  • 支持修改后台线程中的位图。
  • 具有简单的淡入淡出。
  • 有图像加载进度callback。

克隆DroidPartsGram为例:

在这里输入图像说明

You must try this Universal Loader is best. I am using this after done many RnD on lazy loading .

Universal Image Loader

特征

  • Multithread image loading (async or sync)
  • Wide customization of ImageLoader's configuration (thread executors, downloader, decoder, memory and disk cache, display image options, etc.)
  • Many customization options for every display image call (stub images, caching switch, decoding options, Bitmap processing and displaying, etc.)
  • Image caching in memory and/or on disk (device's file system or SD card)
  • Listening loading process (including downloading progress)

Android 2.0+ support

在这里输入图像描述

Just a quick tip for someone who is in indecision regarding what library to use for lazy-loading images:

There are four basic ways.

  1. DIY => Not the best solution but for a few images and if you want to go without the hassle of using others libraries

  2. Volley's Lazy Loading library => From guys at android. It is nice and everything but is poorly documented and hence is a problem to use.

  3. Picasso: A simple solution that just works, you can even specify the exact image size you want to bring in. It is very simple to use but might not be very "performant" for apps that has to deal with humongous amounts of images.

  4. UIL: The best way to lazy load images. You can cache images(you need permission of course), initialize the loader once, then have your work done. The most mature asynchronous image loading library I have ever seen so far.

Check my fork of LazyList . Basically, I improve the LazyList by delaying the call of the ImageView and create two methods:

  1. When you need to put something like "Loading image…"
  2. When you need to show the downloaded image.

I also improved the ImageLoader by implementing a singleton in this object.

All above code have their own worth but with my personal experience just give a try with Picasso.

Picasso is a library specifically for this purpose, in-fact it will manage cache and all other network operations automatically.You will have to add library in your project and just write a single line of code to load image from remote URL.

Please visit here : http://code.tutsplus.com/tutorials/android-sdk-working-with-picasso–cms-22149

I can recommend a different way that works like a charm: Android Query.

You can download that JAR file from here

 AQuery androidAQuery = new AQuery(this); 

举个例子:

 androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW); 

It's very fast and accurate, and using this you can find many more features like animation when loading, getting a bitmap (if needed), etc.

Give Aquery a try. It has amazingly simple methods to load and cache images asynchronously.

URLImageViewHelper is an amazing library that helps you to do that.

 public class ImageDownloader { Map<String, Bitmap> imageCache; public ImageDownloader() { imageCache = new HashMap<String, Bitmap>(); } // download function public void download(String url, ImageView imageView) { if (cancelPotentialDownload(url, imageView)) { // Caching code right here String filename = String.valueOf(url.hashCode()); File f = new File(getCacheDirectory(imageView.getContext()), filename); // Is the bitmap in our memory cache? Bitmap bitmap = null; bitmap = (Bitmap) imageCache.get(f.getPath()); if (bitmap == null) { bitmap = BitmapFactory.decodeFile(f.getPath()); if (bitmap != null) { imageCache.put(f.getPath(), bitmap); } } // No? download it if (bitmap == null) { try { BitmapDownloaderTask task = new BitmapDownloaderTask( imageView); DownloadedDrawable downloadedDrawable = new DownloadedDrawable( task); imageView.setImageDrawable(downloadedDrawable); task.execute(url); } catch (Exception e) { Log.e("Error==>", e.toString()); } } else { // Yes? set the image imageView.setImageBitmap(bitmap); } } } // cancel a download (internal only) private static boolean cancelPotentialDownload(String url, ImageView imageView) { BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); if (bitmapDownloaderTask != null) { String bitmapUrl = bitmapDownloaderTask.url; if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { bitmapDownloaderTask.cancel(true); } else { // The same URL is already being downloaded. return false; } } return true; } // gets an existing download if one exists for the imageview private static BitmapDownloaderTask getBitmapDownloaderTask( ImageView imageView) { if (imageView != null) { Drawable drawable = imageView.getDrawable(); if (drawable instanceof DownloadedDrawable) { DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable; return downloadedDrawable.getBitmapDownloaderTask(); } } return null; } // our caching functions // Find the dir to save cached images private static File getCacheDirectory(Context context) { String sdState = android.os.Environment.getExternalStorageState(); File cacheDir; if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) { File sdDir = android.os.Environment.getExternalStorageDirectory(); // TODO : Change your diretcory here cacheDir = new File(sdDir, "data/ToDo/images"); } else cacheDir = context.getCacheDir(); if (!cacheDir.exists()) cacheDir.mkdirs(); return cacheDir; } private void writeFile(Bitmap bmp, File f) { FileOutputStream out = null; try { out = new FileOutputStream(f); bmp.compress(Bitmap.CompressFormat.PNG, 80, out); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) out.close(); } catch (Exception ex) { } } } // download asynctask public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { private String url; private final WeakReference<ImageView> imageViewReference; public BitmapDownloaderTask(ImageView imageView) { imageViewReference = new WeakReference<ImageView>(imageView); } @Override // Actual download method, run in the task thread protected Bitmap doInBackground(String... params) { // params comes from the execute() call: params[0] is the url. url = (String) params[0]; return downloadBitmap(params[0]); } @Override // Once the image is downloaded, associates it to the imageView protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); // Change bitmap only if this process is still associated with // it if (this == bitmapDownloaderTask) { imageView.setImageBitmap(bitmap); // cache the image String filename = String.valueOf(url.hashCode()); File f = new File( getCacheDirectory(imageView.getContext()), filename); imageCache.put(f.getPath(), bitmap); writeFile(bitmap, f); } } } } static class DownloadedDrawable extends ColorDrawable { private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference; public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) { super(Color.WHITE); bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>( bitmapDownloaderTask); } public BitmapDownloaderTask getBitmapDownloaderTask() { return bitmapDownloaderTaskReference.get(); } } // the actual download code static Bitmap downloadBitmap(String url) { HttpParams params = new BasicHttpParams(); params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); HttpClient client = new DefaultHttpClient(params); final HttpGet getRequest = new HttpGet(url); try { HttpResponse response = client.execute(getRequest); final int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); return null; } final HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); final Bitmap bitmap = BitmapFactory .decodeStream(inputStream); return bitmap; } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (Exception e) { // Could provide a more explicit error message for IOException or // IllegalStateException getRequest.abort(); Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString()); } finally { if (client != null) { // client.close(); } } return null; } } 

You can try the Aquery Android library for lazy loading image and listview… The below code may help you….. download library from here .

 AQuery aq = new AQuery(mContext); aq.id(R.id.image1).image("http://data.whicdn.comhttp://img.dovov.com63995806/original.jpg"); 

I had this issue and implemented lruCache. I believe you need API 12 and above or use the compatiblity v4 library. lurCache is fast memory, but it also has a budget, so if you're worried about that you can use a diskcache… It's all described in Caching Bitmaps .

I'll now provide my implementation which is a singleton I call from anywhere like this:

 //Where the first is a string and the other is a imageview to load. DownloadImageTask.getInstance().loadBitmap(avatarURL, iv_avatar); 

Here's the ideal code to cache and then call the above in getView of an adapter when retrieving the web image:

 public class DownloadImageTask { private LruCache<String, Bitmap> mMemoryCache; /* Create a singleton class to call this from multiple classes */ private static DownloadImageTask instance = null; public static DownloadImageTask getInstance() { if (instance == null) { instance = new DownloadImageTask(); } return instance; } //Lock the constructor from public instances private DownloadImageTask() { // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an // int in its constructor. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in kilobytes rather than // number of items. return bitmap.getByteCount() / 1024; } }; } public void loadBitmap(String avatarURL, ImageView imageView) { final String imageKey = String.valueOf(avatarURL); final Bitmap bitmap = getBitmapFromMemCache(imageKey); if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { imageView.setImageResource(R.drawable.ic_launcher); new DownloadImageTaskViaWeb(imageView).execute(avatarURL); } } private void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } private Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } /* A background process that opens a http stream and decodes a web image. */ class DownloadImageTaskViaWeb extends AsyncTask<String, Void, Bitmap> { ImageView bmImage; public DownloadImageTaskViaWeb(ImageView bmImage) { this.bmImage = bmImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mIcon = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mIcon = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } addBitmapToMemoryCache(String.valueOf(urldisplay), mIcon); return mIcon; } /* After decoding we update the view on the main UI. */ protected void onPostExecute(Bitmap result) { bmImage.setImageBitmap(result); } } } 

Some answers have already mentioned using various image libraries like Universal Image Loader and androidimageloader etc. This is an old quesion but for anyone still looking for something like this, there are several such libraries for image loading/caching.