android开发内存优化——利用软引用
2014-11-10 14:37
211 查看
所有Android的开发者一定都遇到过内存溢出这个头疼的问题,一旦出现这个问题,很难直接确定我们的应用是那里出了问题,要想定位问题的原因,必须通过一些内存分析工具和强大的经验积累才能快速的定位到问题具体出现在那里。
基于移动开发具有的这个特性,本着尽量减少内存消耗的原则,以及我最近遇到的内存堆积(偶尔溢出)问题,总结一下这次解决这个问题的经验。
问题源头:开始App功能没那么多的时候,是没有注意到这个问题的,后来功能越强越多,图片也越来越多的时候,用ADT自带的Allocation Tracker查看了一下内存分配,明显有许多无用的data object,而没有释放掉,开始以为是universalImageLoader的问题,以为这个开源工程对图片的加载有问题,后来把图片全去掉再看内存分配时还是有无用的data object,花了两天时间后发现是,是自己本地的一些bitmap没有回收,一直缓存在内存中,另一个原因就是前面文章提到的,为了实现退出功能,使用了一个全局的ArrayList去存储所有新启动的Activity,导致Activity这种大对象无法释放,有这两个问题内存不堆积才有问题。
定位到问题的所在后,先用前面的广播方式替换掉之前的那种方案,这样就解决了问题的一半了,那本地图片如何处理呢?就上网查看了一些文章,看到许多大神都说到了软引用这个东东,于是就研究了下软引用如何使用。发现这软引用的确是个好东西。的确可以优化整个应用对内存的消耗。
从JDK1.2开始,java将对象分成了四种级别,以达到程序对对象生财周期的灵活控制,这四个级别由强到弱是:强引用,软引用,弱引用,虚引用。强引用就不多说了,就是我们平时直接new出来的一个对象,不做任何的修饰,就是强引用。虚引用暂未使用过也就没做过深入了解,弱引用的使用方式基本和软引用是一样的,所以就重点看了一下应用程序如何使用软引用。
如果一个对象只具有软引用,那么如果内存如果够用的话,GC就不会回收它,如果内存不足了,就会优先回收只有软引用的对象内存,而保证不会内存溢出。基于软引用的这个特性,我们可以使用软引用来实现内存敏感区的高速缓存,因此为了防止内存溢出的发生,在处理一些占用内存较大且声明周期较长的对象的时候,我们可以尽量使用软引用,例如: Context及其子类对象,Drawable及其子类对象,Bitmap位图对象等,在创建这些类的对象的时候,尽量将其声明为软引用。
软引用对象声明: SoftReference<Class> instance;
下面两个例子是我在项目中实际使用的代码,大家可以看下。
基于移动开发具有的这个特性,本着尽量减少内存消耗的原则,以及我最近遇到的内存堆积(偶尔溢出)问题,总结一下这次解决这个问题的经验。
问题源头:开始App功能没那么多的时候,是没有注意到这个问题的,后来功能越强越多,图片也越来越多的时候,用ADT自带的Allocation Tracker查看了一下内存分配,明显有许多无用的data object,而没有释放掉,开始以为是universalImageLoader的问题,以为这个开源工程对图片的加载有问题,后来把图片全去掉再看内存分配时还是有无用的data object,花了两天时间后发现是,是自己本地的一些bitmap没有回收,一直缓存在内存中,另一个原因就是前面文章提到的,为了实现退出功能,使用了一个全局的ArrayList去存储所有新启动的Activity,导致Activity这种大对象无法释放,有这两个问题内存不堆积才有问题。
定位到问题的所在后,先用前面的广播方式替换掉之前的那种方案,这样就解决了问题的一半了,那本地图片如何处理呢?就上网查看了一些文章,看到许多大神都说到了软引用这个东东,于是就研究了下软引用如何使用。发现这软引用的确是个好东西。的确可以优化整个应用对内存的消耗。
从JDK1.2开始,java将对象分成了四种级别,以达到程序对对象生财周期的灵活控制,这四个级别由强到弱是:强引用,软引用,弱引用,虚引用。强引用就不多说了,就是我们平时直接new出来的一个对象,不做任何的修饰,就是强引用。虚引用暂未使用过也就没做过深入了解,弱引用的使用方式基本和软引用是一样的,所以就重点看了一下应用程序如何使用软引用。
如果一个对象只具有软引用,那么如果内存如果够用的话,GC就不会回收它,如果内存不足了,就会优先回收只有软引用的对象内存,而保证不会内存溢出。基于软引用的这个特性,我们可以使用软引用来实现内存敏感区的高速缓存,因此为了防止内存溢出的发生,在处理一些占用内存较大且声明周期较长的对象的时候,我们可以尽量使用软引用,例如: Context及其子类对象,Drawable及其子类对象,Bitmap位图对象等,在创建这些类的对象的时候,尽量将其声明为软引用。
软引用对象声明: SoftReference<Class> instance;
下面两个例子是我在项目中实际使用的代码,大家可以看下。
//这个例子是用来处理生命周期较长的大对象 /********************************************************** * @文件名称:ActivityManager.java * @创建时间:2014年11月6日 上午11:38:23 * @文件描述:Activity管理类 * @修改历史:2014年11月6日创建初始版本 **********************************************************/ public class ActivityManager { private static ActivityManager manager = null; private static HashMap<String, SoftReference<Activity>> activityMap; // 静态语句块,在类加载的时候一起执行 static { manager = new ActivityManager(); activityMap = new HashMap<String, SoftReference<Activity>>(); } private ActivityManager() { } public static ActivityManager getInstance() { return manager; } public void put(Activity act) { activityMap.put(act.toString(), new SoftReference<Activity>(act)); } public void remove(Activity act) { activityMap.remove(act.toString()); } public void finishAllActivity() { Set<String> set = activityMap.keySet(); Iterator<String> iter = set.iterator(); while (iter.hasNext()) { String actName = iter.next(); Activity currentAct = activityMap.get(actName).get(); if (currentAct != null) { currentAct.finish(); currentAct = null; } } activityMap.clear(); activityMap = null; } }
//这个例子是用来处理位图等内存敏感对象示例 public class BitmapManager { private static BitmapManager bitmapManager = null; private static HashMap<String, SoftReference<Bitmap>> imageCache = null; static { bitmapManager = new BitmapManager(); imageCache = new HashMap<String, SoftReference<Bitmap>>(); } private BitmapManager() { } public static BitmapManager getInstance() { return bitmapManager; } public static void saveBitmapToCache(String path) { Bitmap bitmap = BitmapFactory.decodeFile(path); // 添加该对象软引用对象到Map中使其缓存 imageCache.put(path, new SoftReference<Bitmap>(bitmap)); // 使用完后手动将位图对象置null bitmap = null; } public static Bitmap queryBitmapByPath(String path) { // 取出软软引用 SoftReference<Bitmap> softBitmap = imageCache.get(path); // 使用时必须判断软引用是否回收,被回收返回空 if (softBitmap == null) { return null; } Bitmap bitmap = softBitmap.get(); return bitmap; } }总结:在我们开发应用程序时,最好是刚开始实现时就考虑到可能发生的问题,提前就做好这些细节性的处理,就会从根上杜绝这类问题的发生,而当问题发生了再去处理就会花费更多的精力。
相关文章推荐
- Android开发之图片处理专题(一):利用软引用构建图片高速缓存
- Android开发如何利用Google map
- Android开发如何利用Google map总揽
- 16—【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能
- Android腾讯微博客户端开发五:利用FootView实现ListView滑动动态加载实现分页
- 【Android游戏开发十八】解放手指,利用传感器开发游戏!(本文讲解在SurfaceView中用重力传感器控制圆球的各方向移动)
- 利用其他工具(非ADT)开发Android上的应用程序
- android开发LiveWallpaper流程(利用OpenGLES开发)
- Android开发经验小节2:循环利用你的小对象
- Android开发基础(2.2)--利用NDK搭建自己的Android交叉工具链
- Android腾讯微博客户端开发5:利用FootView实现ListView滑动动态加载实现分页
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- 【Android游戏开发十八】解放手指,利用传感器开发游戏!(本文讲解在SurfaceView中用重力传感器控制圆球的各方向移动)
- Android开发经验小节2:循环利用你的小对象
- 利用用Flash Builder 4.5搭建Android 开发平台(附带模拟器)
- 前传,利用android开发环境来开发qt-embedded程序
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- 【Android游戏开发十八】解放手指,利用传感器开发游戏!(本文讲解在SurfaceView中用重力传感器控制圆球的各方向移动)
- Android-x86入门之--如何利用android-x86取代模拟器进行应用程序的开发
- android利用OpenGLES开发动态壁纸用到的GLWallpaperService类