Android图像caching

如何从网上下载图像后caching图像?

而现在的说法是:使用系统caching。

URL url = new URL(strUrl); URLConnection connection = url.openConnection(); connection.setUseCaches(true); Object response = connection.getContent(); if (response instanceof Bitmap) { Bitmap bitmap = (Bitmap)response; } 

提供与浏览器共享的内存和闪存caching。

GRR。 我希望有人告诉我,我写我自己的cachingpipe理器之前。

关于上面的优雅的connection.setUseCaches解决scheme:可悲的是,没有一些额外的努力,它将无法正常工作。 您将需要使用ResponseCache.setDefault安装ResponseCache.setDefault 。 否则, HttpURLConnection将默默地忽略setUseCaches(true)位。

有关详细信息,请参阅FileResponseCache.java顶部的FileResponseCache.java

http://libs-for-android.googlecode.com/svn/reference/com/google/android/filecache/FileResponseCache.html

(我会在评论中张贴这个,但我显然没有足够的业力。)

将它们转换成Bitmaps,然后将它们存储在一个Collection(HashMap,List等)中,或者你可以把它们写在SDcard上。

当使用第一种方法将它们存储在应用程序空间中时,如果它们的数量很大(以便在危机期间收集垃圾),则可能需要将它们包装在java.lang.ref.SoftReference中 。 这可能会发生重新加载。

 HashMap<String,SoftReference<Bitmap>> imageCache = new HashMap<String,SoftReference<Bitmap>>(); 

写在SDcard上不需要重新加载; 只是一个用户权限。

要下载图像并保存到存储卡,可以这样做。

 //First create a new URL object URL url = new URL("http://www.google.co.uk/logos/holiday09_2.gif") //Next create a file, the example below will save to the SDCARD using JPEG format File file = new File("/sdcard/example.jpg"); //Next create a Bitmap object and download the image to bitmap Bitmap bitmap = BitmapFactory.decodeStream(url.openStream()); //Finally compress the bitmap, saving to the file previously created bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file)); 

不要忘记将Internet权限添加到您的清单:

 <uses-permission android:name="android.permission.INTERNET" /> 

使用LruCache高效地caching图像。 您可以从Android开发人员网站了解有关LruCache信息

我已经使用下面的解决scheme在Android中的图像下载和caching。 您可以按照以下步骤操作:

第1 ImagesCache 制作Class Named ImagesCache 。 我Singleton object for this class使用了Singleton object for this class

 import android.graphics.Bitmap; import android.support.v4.util.LruCache; public class ImagesCache { private LruCache<String, Bitmap> imagesWarehouse; private static ImagesCache cache; public static ImagesCache getInstance() { if(cache == null) { cache = new ImagesCache(); } return cache; } public void initializeCache() { final int maxMemory = (int) (Runtime.getRuntime().maxMemory() /1024); final int cacheSize = maxMemory / 8; System.out.println("cache size = "+cacheSize); imagesWarehouse = new LruCache<String, Bitmap>(cacheSize) { protected int sizeOf(String key, Bitmap value) { // The cache size will be measured in kilobytes rather than number of items. int bitmapByteCount = value.getRowBytes() * value.getHeight(); return bitmapByteCount / 1024; } }; } public void addImageToWarehouse(String key, Bitmap value) { if(imagesWarehouse != null && imagesWarehouse.get(key) == null) { imagesWarehouse.put(key, value); } } public Bitmap getImageFromWarehouse(String key) { if(key != null) { return imagesWarehouse.get(key); } else { return null; } } public void removeImageFromWarehouse(String key) { imagesWarehouse.remove(key); } public void clearCache() { if(imagesWarehouse != null) { imagesWarehouse.evictAll(); } } } 

第2步:

创build另一个名为DownloadImageTask的类,如果位图在高速caching中不可用,则会从此处下载它:

 public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { private int inSampleSize = 0; private String imageUrl; private BaseAdapter adapter; private ImagesCache cache; private int desiredWidth, desiredHeight; private Bitmap image = null; private ImageView ivImageView; public DownloadImageTask(BaseAdapter adapter, int desiredWidth, int desiredHeight) { this.adapter = adapter; this.cache = ImagesCache.getInstance(); this.desiredWidth = desiredWidth; this.desiredHeight = desiredHeight; } public DownloadImageTask(ImagesCache cache, ImageView ivImageView, int desireWidth, int desireHeight) { this.cache = cache; this.ivImageView = ivImageView; this.desiredHeight = desireHeight; this.desiredWidth = desireWidth; } @Override protected Bitmap doInBackground(String... params) { imageUrl = params[0]; return getImage(imageUrl); } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); if(result != null) { cache.addImageToWarehouse(imageUrl, result); if(ivImageView != null) { ivImageView.setImageBitmap(result); } else { } if(adapter != null) { adapter.notifyDataSetChanged(); } } } private Bitmap getImage(String imageUrl) { if(cache.getImageFromWarehouse(imageUrl) == null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; options.inSampleSize = inSampleSize; try { URL url = new URL(imageUrl); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); InputStream stream = connection.getInputStream(); image = BitmapFactory.decodeStream(stream, null, options); int imageWidth = options.outWidth; int imageHeight = options.outHeight; if(imageWidth > desiredWidth || imageHeight > desiredHeight) { System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight); inSampleSize = inSampleSize + 2; getImage(imageUrl); } else { options.inJustDecodeBounds = false; connection = (HttpURLConnection)url.openConnection(); stream = connection.getInputStream(); image = BitmapFactory.decodeStream(stream, null, options); return image; } } catch(Exception e) { Log.e("getImage", e.toString()); } } return image; } 

第3步:使用您的ActivityAdapter

注意:如果你想从Activity类的URL加载图像。 使用DownloadImageTask的第二个构造函数,但是如果要从Adapter显示图像,请使用DownloadImageTask第一个构造函数(例如,您在ListView有一个图像,并且正在从“适配器”设置图像)

使用活动:

 ImageView imv = (ImageView) findViewById(R.id.imageView); ImagesCache cache = ImagesCache.getInstance();//Singleton instance handled in ImagesCache class. cache.initializeCache(); String img = "your_image_url_here"; Bitmap bm = cache.getImageFromWarehouse(img); if(bm != null) { imv.setImageBitmap(bm); } else { imv.setImageBitmap(null); DownloadImageTask imgTask = new DownloadImageTask(cache, imv, 300, 300);//Since you are using it from `Activity` call second Constructor. imgTask.execute(img); } 

适配器的用法:

 ImageView imv = (ImageView) rowView.findViewById(R.id.imageView); ImagesCache cache = ImagesCache.getInstance(); cache.initializeCache(); String img = "your_image_url_here"; Bitmap bm = cache.getImageFromWarehouse(img); if(bm != null) { imv.setImageBitmap(bm); } else { imv.setImageBitmap(null); DownloadImageTask imgTask = new DownloadImageTask(this, 300, 300);//Since you are using it from `Adapter` call first Constructor. imgTask.execute(img); } 

注意:

cache.initializeCache()可以在应用程序的第一个Activity中使用这个语句。 一旦你初始化了caching,如果你正在使用ImagesCache实例,你永远不需要每次都初始化它。

我从来没有擅长解释的东西,但希望这将有助于初学者,如何caching使用LruCache及其用法:)

编辑:

现在有一天,有非常着名的图书馆被称为PicassoGlide ,可以用来在Android应用程序非常有效地加载图像。 尝试这个非常简单和有用的图书馆毕加索为Android和Glide为Android 。 您不必担心caching图像。

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

像毕加索一样,滑动可以加载和显示来自多个来源的图像,同时在进行image processing时也可以caching并保持较低的内存影响。 它已被官方Google应用程序(例如Google I / O 2015应用程序)使用,并且与Picasso一样受欢迎。 在这个系列中,我们将探索滑翔毕加索的差异和优势。

你也可以访问博客Glide和毕加索之间的区别

我会考虑使用droidfu的图像caching。 它实现了内存和基于磁盘的图像caching。 您还将获得一个利用ImageCache库的WebImageView。

这里是droidfu和WebImageView的完整描述: http ://brainflush.wordpress.com/2009/11/23/droid-fu-part-2-webimageview-and-webgalleryadapter/

我已经尝试了SoftReferences,他们太积极地回收在Android中,我觉得没有意义使用它们

正如雷兔build议的那样,ImageDownloader是这个工作中最好的一个。 我还发现这个class稍有变化:

http://theandroidcoder.com/utilities/android-image-download-and-caching/

两者之间的主要区别在于ImageDownloader使用Androidcaching系统,修改后的系统使用内部和外部存储器作为caching,无限期地保留caching的图像,或直到用户手动删除caching的图像。 作者还提到了Android 2.1的兼容性。

这是Joe的一个好习惯。 上面的代码示例有两个问题 – 一个 – 响应对象不是一个位图的实例(当我的URL引用一个JPG,如http:\ website.com \ image.jpg,它的一个

org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl $ LimitedInputStream)。

其次,正如Joe指出的,没有configuration响应caching,就不会发生caching。 Android开发者只剩下自己的caching。 这里有一个例子,但它只caching在内存中,这实际上不是完整的解决scheme。

http://codebycoffee.com/2010/06/29/using-responsecache-in-an-android-app/

URLConnectioncachingAPI在这里描述:

http://download.oracle.com/javase/6/docs/technotes/guides/net/http-cache.html

我仍然认为这是走这条路线的一个很好的解决scheme – 但是你仍然需要写一个caching。 听起来很有趣,但我宁愿写function。

有关Android的官方培训部分有一个特殊的条目: http : //developer.android.com/training/displaying-bitmaps/cache-bitmap.html

这个部分是相当新的,当问题被问到的时候不在那里。

build议的解决scheme是使用LruCache。 该类是在Honeycomb中引入的,但它也包含在兼容性库中。

您可以通过设置最大数量或条目来初始化LruCache,并且它会自动将您的数据分类并在超出限制时清理使用较less的数据。 除此之外,它被用作一个正常的地图。

来自官方网页的示例代码:

 private LruCache mMemoryCache; @Override protected void onCreate(Bundle savedInstanceState) { ... // Get memory class of this device, exceeding this amount will throw an // OutOfMemory exception. final int memClass = ((ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE)).getMemoryClass(); // Use 1/8th of the available memory for this memory cache. final int cacheSize = 1024 * 1024 * memClass / 8; mMemoryCache = new LruCache(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in bytes rather than number of items. return bitmap.getByteCount(); } }; ... } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } 

以前SoftReferences是一个很好的select,但不再是从官方网页引用:

注意:过去,stream行的内存caching实现是SoftReference或WeakReference位图caching,但不build议这样做。 从Android 2.3(API Level 9)开始,垃圾收集器更加积极地收集软/弱引用,这使得它们相当无效。 另外,在Android 3.0(API Level 11)之前,位图的备份数据被存储在本地存储器中,而不是以可预见的方式释放,这可能导致应用程序暂时超出其内存限制和崩溃。

考虑使用Sergey Tarasevich的 Universal Image Loader库 。 它附带:

  • multithreading图像加载。 它可以让你定义线程池的大小
  • 内存中的图像caching,设备的文件系统和SD卡。
  • 可以听取加载进度和加载事件

通用映像加载程序允许对下载的映像进行详细的cachingpipe理 ,具有以下cachingconfiguration:

  • UsingFreqLimitedMemoryCache :当超过caching大小限制时, 最不经常使用的位图将被删除。
  • LRULimitedMemoryCache :当超过caching大小限制时,删除最近最less使用的位图。
  • FIFOLimitedMemoryCache :当超过caching大小限制时,FIFO规则用于删除。
  • LargestLimitedMemoryCache :超过caching大小限制时,将删除最大的位图。
  • LimitedAgeMemoryCache :caching对象在其年龄超过定义值时被删除。
  • WeakMemoryCache :一个只有弱点引用位图的内存caching。

一个简单的用法示例:

 ImageView imageView = groupView.findViewById(R.id.imageView); String imageUrl = "http://site.com/image.png"; ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.init(ImageLoaderConfiguration.createDefault(context)); imageLoader.displayImage(imageUrl, imageView); 

本示例使用默认的UsingFreqLimitedMemoryCache

实际上我的工作是在我的Main类上设置ResponseCache:

 try { File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http"); long httpCacheSize = 10 * 1024 * 1024; // 10 MiB HttpResponseCache.install(httpCacheDir, httpCacheSize); } catch (IOException e) { } 

 connection.setUseCaches(true); 

下载位图时。

http://practicaldroid.blogspot.com/2013/01/utilizing-http-response-cache.html

Google的libs-for-android有一个很好的库来pipe理图像和文件caching。

http://code.google.com/p/libs-for-android/

我一直在摔跤一段时间, 使用SoftReferences的答案会太快地丢失数据。 build议实例化RequestCache的答案太乱了,再加上我永远找不到完整的示例。

但ImageDownloader.java奇妙的为我工作。 它使用一个HashMap,直到容量达到或清除超时发生,然后事物被移动到一个SoftReference,从而使用两全其美。

甚至以后回答,但我写了一个Android图像pipe理器,透明地处理caching(内存和磁盘)。 代码在Github上https://github.com/felipecsl/Android-ImageManager

迟到的答案,但我想我应该添加一个链接到我的网站,因为我已经写了一个教程如何使图像caching的android: http : //squarewolf.nl/2010/11/android-image-cache/ 更新:由于来源已过时,该网页已被移除。 我在她的build议中join@elenasys来使用Ignition 。

所有遇到这个问题的人都没有find解决办法:希望你喜欢! = d