http://www.bdqn.cn/news/201307/10432.shtml
使用图片缓存技术
在 你应用程序的UI界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来。在很多情况下,(比如使用 ListView, GridView 或者 ViewPager 这样的组件),屏幕上显示的图片可以通过滑动屏幕等事件不断地增加,最终导致OOM。
为 了保证内存的使用始终维持在一个合理的范围,通常会把被移除屏幕的图片进行回收处理。此时垃圾回收器也会认为你不再持有这些图片的引用,从而对这些图片进 行GC操作。用这种思路来解决问题是非常好的,可是为了能让程序快速运行,在界面上迅速地加载图片,你又必须要考虑到某些图片被回收之后,用户又将它重新 滑入屏幕这种情况。这时重新去加载一遍刚刚加载过的图片无疑是性能的瓶颈,你需要想办法去避免这个情况的发生。
这个时候,使用内存缓存技术可以很好的解决这个问题,它可以让组件快速地重新加载和处理图片。下面我们就来看一看如何使用内存缓存技术来对图片进行缓存,从而让你的应用程序在加载很多图片的时候可以提高响应速度和流畅性。
内 存缓存技术对那些大量占用应用程序宝贵内存的图片提供了快速访问的方法。其中最核心的类是LruCache (此类在android-support-v4的包中提供) 。这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
在 过去,我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。
为了能够选择一个合适的缓存大小给LruCache, 有以下多个因素应该放入考虑范围内,例如:
你的设备可以为每个应用程序分配多大的内存?
设备屏幕上一次最多能显示多少张图片?有多少图片需要进行预加载,因为有可能很快也会显示在屏幕上?
你的设备的屏幕大小和分辨率分别是多少?一个超高分辨率的设备(例如 Galaxy Nexus) 比起一个较低分辨率的设备(例如 Nexus S),在持有相同数量图片的时候,需要更大的缓存空间。
图片的尺寸和大小,还有每张图片会占据多少内存空间。
图片被访问的频率有多高?会不会有一些图片的访问频率比其它图片要高?如果有的话,你也许应该让一些图片常驻在内存当中,或者使用多个LruCache 对象来区分不同组的图片。
你能维持好数量和质量之间的平衡吗?有些时候,存储多个低像素的图片,而在后台去开线程加载高像素的图片会更加的有效。
并 没有一个指定的缓存大小可以满足所有的应用程序,这是由你决定的。你应该去分析程序内存的使用情况,然后制定出一个合适的解决方案。一个太小的缓存空间, 有可能造成图片频繁地被释放和重新加载,这并没有好处。而一个太大的缓存空间,则有可能还是会引起 java.lang.OutOfMemory 的异常。
下面是一个使用 LruCache 来缓存图片的例子:
[java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
private LruCache<String, Bitmap> mMemoryCache;
@Override protected void onCreate(Bundle savedInstanceState) {
// 获取到可用内存的最大值,使用内存超出这个值会引起OutOfMemory异常。
// LruCache通过构造函数传入缓存值,以KB为单位。
int maxMemory = ( int ) (Runtime.getRuntime().maxMemory() / 1024 );
// 使用最大可用内存值的1/8作为缓存的大小。
int cacheSize = maxMemory / 8 ;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// 重写此方法来衡量每张图片的大小,默认返回图片数量。
return bitmap.getByteCount() / 1024 ;
}
};
} public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null ) {
mMemoryCache.put(key, bitmap);
}
} public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
} |
在 这个例子当中,使用了系统分配给应用程序的八分之一内存来作为缓存大小。在中高配置的手机当中,这大概会有4兆(32/8)的缓存空间。一个全屏幕的 GridView 使用4张 800x480分辨率的图片来填充,则大概会占用1.5兆的空间(800*480*4)。因此,这个缓存大小可以存储2.5页的图片。
当向 ImageView 中加载一张图片时,首先会在 LruCache 的缓存中进行检查。如果找到了相应的键值,则会立刻更新ImageView ,否则开启一个后台线程来加载这张图片。
[java]
1
2
3
4
5
6
7
8
9
10
11
|
public void loadBitmap( int resId, ImageView imageView) {
final String imageKey = String.valueOf(resId);
final Bitmap bitmap = getBitmapFromMemCache(imageKey);
if (bitmap != null ) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(R.drawable.image_placeholder);
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
} |
BitmapWorkerTask 还要把新加载的图片的键值对放到缓存中。
[java]
1
2
3
4
5
6
7
8
9
10
|
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
// 在后台加载图片。
@Override
protected Bitmap doInBackground(Integer... params) {
final Bitmap bitmap = decodeSampledBitmapFromResource(
getResources(), params[ 0 ], 100 , 100 );
addBitmapToMemoryCache(String.valueOf(params[ 0 ]), bitmap);
return bitmap;
}
} |
相关推荐
本文将详细介绍如何在Android应用中使用`LruCache`来缓存图片。 **1. LruCache的基本原理** LRU(Least Recently Used)算法是一种常用的页面替换策略,当缓存满时,会优先淘汰最近最少使用的数据。`LruCache`是...
案例包含Android-Universal-Image-Loader 网络图片加载框架实现图片加载和结合universal-image-loader与LruCache来自定义缓存图片,可以设置缓存与不缓存。 博客地址:...
本文将深入探讨如何结合BaseAdapter、AsyncTask以及LruCache来实现高效、流畅的网络图片加载。 首先,`BaseAdapter`是自定义适配器的一种基本形式,用于填充ListView的数据。它需要重写`getCount()`、`getItem()`、...
"LruCache缓存网络图片"这个主题主要涉及到Android内存缓存的一种实现方式——LRU(Least Recently Used)最近最少使用算法。LRUCache是Android SDK提供的一种基于LRU算法的内存缓存工具,它被广泛应用于存储像图片...
README之前遇到 asynctask 多次调用的异常,因为 GetImageFromHTTP 只有一个实例,多次调用就会有异常抛出现在暂时每次请求下载图片时,都新建一个 asynctask 对象去执行,但是第一次加载时,也会遇到性能低下的问题...
通过这种方式,我们可以有效地利用`LruCache`在ListView中缓存图片,提高图片加载速度,减少对系统资源的占用。不过,需要注意的是,虽然`LruCache`能够优化内存管理,但不能解决所有问题。对于大量图片的加载,可能...
标题“LruCache缓存demo”指的是一个关于如何使用LRUCache进行缓存操作的实际示例。通过这个示例,我们可以学习如何在Android应用中有效地管理内存,防止因频繁加载数据导致的内存压力过大。 描述中提到的链接指向...
在Android开发中,`LruCache`是Google提供的一种基于LRU算法实现的缓存机制,它被广泛应用于图片、数据库查询结果等数据的缓存,以提高应用性能和用户体验。 ### LRU算法原理 LRU算法的基本思想是:当内存空间满时...
这个Demo项目涵盖了多个关键知识点,包括异步加载、网络编程、JSON解析以及LruCache图片缓存策略,这些都是在实际开发中处理数据流和用户体验优化的重要技术。 1. **异步加载**: 在Android中,为了防止UI线程被...
5. **显示缓存图片**: 在实际应用中,我们通常会使用一个自定义的ImageView来加载和显示图片。在加载图片时,首先检查`LruCache`中是否有缓存,如果有则直接显示,否则从网络或其他来源加载并放入缓存: ```java ...
- **图片缓存**:在加载大量图片的应用场景中,LRUCache可以有效减少重复加载相同的图片,提高加载速度。 - **数据缓存**:对于频繁读取数据库的数据查询结果,使用LRUCache可以在内存中缓存这些结果,减少数据库的...
本文主要讨论了Android中的LruCache缓存策略,它是一种高效的内存管理机制,尤其适用于图片或者其他大对象的缓存。 一、Android缓存策略概述 缓存的基本操作包括添加、获取和删除。在Android系统中,内存缓存和...
AsyncTask的使用及ListView的常见优化 asyncTask异步加载数据 使用了LruCache优化图片加载 通过滑动监听提高ListView滑动流畅度.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习...
本篇文章将深入探讨如何在Android中有效地加载大图和多图,并介绍LruCache缓存机制来优化内存使用。 首先,Android系统对每个应用都有一定的内存限制。当图片过大,直接加载到内存可能导致OutOfMemory(OOM)异常。...
为了提高用户体验,开发者通常会采用缓存机制来存储图片,减少网络请求,加快图片显示速度。本文将深入探讨如何使用`LruCache`和`DiskLruCache`实现一个二级缓存的自定义`ImageLoader`。 `LruCache`是Android SDK...
10. **性能优化**: 在处理大量图片时,要注意内存优化,如使用LruCache缓存图片、避免重复加载和及时释放不再使用的资源。 11. **源码分析**: "源码说明.txt"可能是对代码实现的简要解释,阅读它可以帮助理解代码的...
- 考虑内存优化,如使用LruCache缓存图片,避免内存泄漏。 7. **兼容性和适配**: - 需要考虑不同设备的屏幕尺寸和方向,以及横竖屏切换时的布局适配。 - 在低版本Android系统上测试,确保兼容性。 8. **动画...
11. **性能优化**:考虑到Android设备的多样性,开发者可能对应用进行了性能优化,如使用LruCache缓存图片、异步加载机制和适配不同分辨率的屏幕。 12. **测试与调试**:项目开发过程中,单元测试、集成测试和性能...
6. 性能优化:考虑到可能处理大量的图片,我们需要关注内存管理和性能优化,比如使用LruCache缓存图片,避免内存泄漏,以及合理使用异步加载策略。 7. 图片保存与分享:完成拼图后,用户可能希望保存作品或分享给...
7. **利用LruCache缓存图片**:可以自定义一个内存缓存策略,如使用`LruCache`,缓存帧动画的图片,避免重复加载。 8. **使用Drawable动画替代帧动画**:对于复杂动画,可以考虑使用`ObjectAnimator`、`...