A. 在android开发中,有哪些好的内存优化方式
可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。
2. 避免在Android里面使用Enum
Android官方培训课程提到过“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。
3. 减小Bitmap对象的内存占用
Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,,通常来说有以下2个措施:
inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异
4.Bitmap对象的复用
缩小Bitmap的同时,也需要提高BitMap对象的复用率,避免频繁创建BitMap对象,复用的方法有以下2个措施
LRUCache : “最近最少使用算法”在Android中有极其普遍的应用。ListView与GridView等显示大量图片的控件里,就是使用LRU的机制来缓存处理好的Bitmap,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据,
inBitMap高级特性:利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小
4. 使用更小的图片
在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。
5.StringBuilder
在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。
6.避免在onDraw方法里面执行对象的创建
类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。
7. 避免对象的内存泄露
类的静态变量持有大数据对象
静态变量长期维持到大数据对象的引用,阻止垃圾回收。
非静态内部类存在静态实例
非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。
资源对象未关闭
资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们, 以便它们的缓冲及时回收内存。它们的缓冲不仅存在于java虚拟机内,还存在于java虚拟机外。 如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄露。
解决办法: 比如SQLiteCursor(在析构函数finalize(),如果我们没有关闭它,它自己会调close()关闭), 如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。 因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null. 在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小, 对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险,记得try catch后,在finally方法中关闭连接
Handler内存泄漏
Handler作为内部类存在于Activity中,但是Handler生命周期与Activity生命周期往往并不是相同的,比如当Handler对象有Message在排队,则无法释放,进而导致本该释放的Acitivity也没有办法进行回收。
B. 怎么把图片压缩到100K以内呀
将图片压缩到100k以内的方法如下:
首先打开计算机,在计算机内打开PS,然后在PS界面内找到”打开“选项并使用鼠标单击打开需要压缩的图片。然后在界面内找到”图像“选项并单击,再在弹出的选项栏内找到”图像大小“选项并使用鼠标单击打开。
然后在弹出的界面内找到宽度和高度并将它们设置为100即可成功将图片压缩到100k以内。
文件格式
BMP格式
位图(外语简称:BMP、外语全称:Bitmap),它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。
这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点——占用磁盘空间过大,所以,BMP在单机上比较流行。
GIF格式
图形交换格式(外语简称:GIF、外语全称:Graphics Interchange Format),美国一家着名的在线信息服务机构CompuServe针对当时网络传输带宽的限制,开发出了这种GIF图像格式。
GIF格式的特点是压缩比高,磁盘空间占用较少,所以这种图像格式迅速得到了广泛的应用。最初的GIF只是简单地用来存储单幅静止图像(称为GIF87a),后来随着技术发展,可以同时存储若干幅静止图像进而形成连续的动画。
使之成为当时支持2D动画为数不多的格式之一(称为GIF89a),而在GIF89a图像中可指定透明区域,使图像具有非同一般的显示效果,这更使GIF风光十足。在Internet上大量采用的彩色动画文件多为这种格式的文件,也称为GIF89a格式文件。
此外,考虑到网络传输中的实际情况,GIF图像格式还增加了渐显方式,也就是说,在图像传输过程中,用户可以先看到图像的大致轮廓,然后随着传输过程的继续而逐步看清图像中的细节部分,从而适应了用户“从朦胧到清楚”的观赏心理。
以上内容参考:网络-图片
C. 谁有java语言实现的bitmap马赛克算法,在线等哦,亲哦,大神们哦!
木有,不知道怎么搞
D. 如何高效使用和管理Bitmap
一、图片加载流程
首先,我们谈谈加载图片的流程,项目中的该模块处理流程如下:
1.在UI主线程中,从内存缓存中获取图片,找到后返回。找不到进入下一步;
2.在工作线程中,从磁盘缓存中获取图片,找到即返回并更新内存缓存。找不到进入下一步;
3.在工作线程中,从网络中获取图片,找到即返回并同时更新内存缓存和磁盘缓存。找不到显示默认以提示。
二、内存缓存类(PanoMemCache)
这里使用Android提供的LruCache类,该类保存一个强引用来限制内容数量,每当Item被访问的时候,此Item就会移动到队列的头部。当cache已满的时候加入新的item时,在队列尾部的item会被回收。
[java] view plain print ?
public class PanoMemoryCache {
// LinkedHashMap初始容量
private static final int INITIAL_CAPACITY = 16;
// LinkedHashMap加载因子
private static final int LOAD_FACTOR = 0.75f;
// LinkedHashMap排序模式
private static final boolean ACCESS_ORDER = true;
// 软引用缓存
private static LinkedHashMap<String, SoftReference<Bitmap>> mSoftCache;
// 硬引用缓存
private static LruCache<String, Bitmap> mLruCache;
public PanoMemoryCache() {
// 获取单个进程可用内存的最大值
// 方式一:使用ActivityManager服务(计量单位为M)
/*int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();*/
// 方式二:使用Runtime类(计量单位为Byte)
final int memClass = (int) Runtime.getRuntime().maxMemory();
// 设置为可用内存的1/4(按Byte计算)
final int cacheSize = memClass / 4;
mLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
if(value != null) {
// 计算存储bitmap所占用的字节数
return value.getRowBytes() * value.getHeight();
} else {
return 0;
}
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
if(oldValue != null) {
// 当硬引用缓存容量已满时,会使用LRU算法将最近没有被使用的图片转入软引用缓存
mSoftCache.put(key, new SoftReference<Bitmap>(oldValue));
}
}
};
/*
* 第一个参数:初始容量(默认16)
* 第二个参数:加载因子(默认0.75)
* 第三个参数:排序模式(true:按访问次数排序;false:按插入顺序排序)
*/
mSoftCache = new LinkedHashMap<String, SoftReference<Bitmap>>(INITIAL_CAPACITY, LOAD_FACTOR, ACCESS_ORDER) {
private static final long serialVersionUID = 7237325113220820312L;
@Override
protected boolean removeEldestEntry(Entry<String, SoftReference<Bitmap>> eldest) {
if(size() > SOFT_CACHE_SIZE) {
return true;
}
return false;
}
};
}
/**
* 从缓存中获取Bitmap
* @param url
* @return bitmap
*/
public Bitmap getBitmapFromMem(String url) {
Bitmap bitmap = null;
// 先从硬引用缓存中获取
synchronized (mLruCache) {
bitmap = mLruCache.get(url);
if(bitmap != null) {
// 找到该Bitmap之后,将其移到LinkedHashMap的最前面,保证它在LRU算法中将被最后删除。
mLruCache.remove(url);
mLruCache.put(url, bitmap);
return bitmap;
}
}
// 再从软引用缓存中获取
synchronized (mSoftCache) {
SoftReference<Bitmap> bitmapReference = mSoftCache.get(url);
if(bitmapReference != null) {
bitmap = bitmapReference.get();
if(bitmap != null) {
// 找到该Bitmap之后,将它移到硬引用缓存。并从软引用缓存中删除。
mLruCache.put(url, bitmap);
mSoftCache.remove(url);
return bitmap;
} else {
mSoftCache.remove(url);
}
}
}
return null;
}
/**
* 添加Bitmap到内存缓存
* @param url
* @param bitmap
*/
public void addBitmapToCache(String url, Bitmap bitmap) {
if(bitmap != null) {
synchronized (mLruCache) {
mLruCache.put(url, bitmap);
}
}
}
/**
* 清理软引用缓存
*/
public void clearCache() {
mSoftCache.clear();
mSoftCache = null;
}
}
补充一点,由于4.0平台以后对SoftReference类引用的对象调整了回收策略,所以该类中的软引用缓存实际上没什么效果,可以去掉。2.3以前平台建议保留。
三、磁盘缓存类(PanoDiskCache)
五、使用decodeByteArray()还是decodeStream()?
讲到这里,有童鞋可能会问我为什么使用BitmapFactory.decodeByteArray(data, 0, data.length, opts)来创建Bitmap,而非使用BitmapFactory.decodeStream(is, null, opts)。你这样做不是要多写一个静态方法readInputStream()吗?
没错,decodeStream()确实是该使用情景下的首选方法,但是在有些情形下,它会导致图片资源不能即时获取,或者说图片被它偷偷地缓存起来,交 还给我们的时间有点长。但是延迟性是致命的,我们等不起。所以在这里选用decodeByteArray()获取,它直接从字节数组中获取,贴近于底层 IO、脱离平台限制、使用起来风险更小。
六、引入缓存机制后获取图片的方法
[java] view plain print ?
/**
* 加载Bitmap
* @param url
* @return
*/
private Bitmap loadBitmap(String url) {
// 从内存缓存中获取,推荐在主UI线程中进行
Bitmap bitmap = memCache.getBitmapFromMem(url);
if(bitmap == null) {
// 从文件缓存中获取,推荐在工作线程中进行
bitmap = diskCache.getBitmapFromDisk(url);
if(bitmap == null) {
// 从网络上获取,不用推荐了吧,地球人都知道~_~
bitmap = PanoUtils.downloadBitmap(this, url);
if(bitmap != null) {
diskCache.addBitmapToCache(bitmap, url);
memCache.addBitmapToCache(url, bitmap);
}
} else {
memCache.addBitmapToCache(url, bitmap);
}
}
return bitmap;
}
七、工作线程池化
有关多线程的切换问题以及在UI线程中执行loadBitmap()方法无效的问题,请参见另一篇博文: 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”。
有关工作线程的处理方式,这里推荐使用定制线程池的方式,核心代码如下:
[java] view plain print ?
// 线程池初始容量
private static final int POOL_SIZE = 4;
private ExecutorService executorService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取当前使用设备的CPU个数
int cpuNums = Runtime.getRuntime().availableProcessors();
// 预开启线程池数目
executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);
...
executorService.submit(new Runnable() {
// 此处执行一些耗时工作,不要涉及UI工作。如果遇到,直接转交UI主线程
pano.setImage(loadBitmap(url));
});
...
}
我们知道,线程构造也是比较耗资源的。一定要对其进行有效的管理和维护。千万不要随意而行,一张图片的工作线程不搭理也许没什么,当使用场景变为 ListView和GridView时,线程池化工作就显得尤为重要了。Android不是提供了AsyncTask吗?为什么不用它?其实 AsyncTask底层也是靠线程池支持的,它默认分配的线程数是128,是远大于我们定制的executorService。
E. 如何解决bitmap 内存溢出out of memory的问题
android 中用bitmap 时很容易内存溢出,报如下错误:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget
● 主要是加上这段:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
● eg1:(通过Uri取图片)
private ImageView preview;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
Bitmap bitmap = BitmapFactory.decodeStream(cr
.openInputStream(uri), null, options);
preview.setImageBitmap(bitmap);
以上代码可以优化内存溢出,但它只是改变图片大小,并不能彻底解决内存溢出。
● eg2:(通过路径去图片)
private ImageView preview;
private String fileName= "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg";
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
Bitmap b = BitmapFactory.decodeFile(fileName, options);
preview.setImageBitmap(b);
filePath.setText(fileName);
★Android 还有一些性能优化的方法:
● 首先内存方面,可以参考 Android堆内存也可自己定义大小 和 优化Dalvik虚拟机的堆内存分配
● 基础类型上,因为Java没有实际的指针,在敏感运算方面还是要借助NDK来完成。Android123提示游戏开发者,这点比较有意思的是Google推出NDK可能是帮助游戏开发人员,比如OpenGL ES的支持有明显的改观,本地代码操作图形界面是很必要的。
● 图形对象优化,这里要说的是Android上的Bitmap对象销毁,可以借助recycle()方法显示让GC回收一个Bitmap对象,通常对一个不用的Bitmap可以使用下面的方式,如
if(bitmapObject.isRecycled()==false) //如果没有回收
bitmapObject.recycle();
● 目前系统对动画支持比较弱智对于常规应用的补间过渡效果可以,但是对于游戏而言一般的美工可能习惯了GIF方式的统一处理,目前 Android系统仅能预览GIF的第一帧,可以借助J2ME中通过线程和自己写解析器的方式来读取GIF89格式的资源。
● 对于大多数Android手机没有过多的物理按键可能我们需要想象下了做好手势识别 GestureDetector 和重力感应来实现操控。通常我们还要考虑误操作问题的降噪处理。
Android堆内存也可自己定义大小
对于一些大型Android项目或游戏来说在算法处理上没有问题外,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对性能的影响十分敏感,除了上次Android开发网提到的 优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理,我们将在下次提到具体应用。
优化Dalvik虚拟机的堆内存分配
对于Android平台来说,其托管层使用的Dalvik JavaVM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体原理我们可以参考开源工程,这里我们仅说下使用方法: private final static floatTARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。
F. 安卓编程用什么软件
一:Java SE 编程
Java 是一种面向对象的开发语言,Android操作系统的应用层使用Java语言来开发,所以要想进行Android开发必须有良好的Java基础。这一阶段的学习,要牢固掌握Java 中的基本语法,掌握面向对象的程序设计思想,及开发工具的使用。之后学习常用类,多线程等高级特性,学习Java网络编程,了解网络通讯结构,掌握数据库语言及JDBC对数据库的访问,了解数据结构与算法,设计模式,项目开发工具的使用等内容。为后续的学习打一夯实的基础。
二:Android 基础应用开发
这一阶段的学习主要是掌握Android的系统架构,熟悉整个android开发环境的搭建,以及的常用命令和工具的使用,熟练掌握Andoid的UI开发,包括使用标准控件,以及自定义各式各样的UI控件,配合动画部分的使用,让自己UI设计更加炫丽更加吸引。最后在自己的应用中植入广告,发布到Market中,享受挣钱的乐趣。
三:Android 核心组件开发
精通Android应用开发核心组件的使用,包括Acitivity窗口活动管理;连接各个组件起到通讯作用的Intent信使;存在于服务端不可见的Service组件;为数据提供共享的ContentProvider;之后要掌握Andorid中很实用的数据存储,以及复习Java中的网络技术,并将它结合到android的开发当中,特别是常用的http通信,以及XML,Json数据的解析。中间通过不同项目让我们去强化该部分的知识。
四:Android 深入开发
通过前面的三个阶段的学习,这一阶段主要是把前面的内容作为基础,结合一些实际的应用,让Android开发更加多样化,当然需要一些练习了,不妨可以尝试一下多媒体方面,如:音视频播放,照相机,闹钟等;常用设备方面,如:GPS,重力传感器,指南针等;还有基本的Android图形开发,绘制自己的View部件以及通过Bitmap对图片作一些处理。然后在此基础之上,学习高级的游戏开发引擎,2D,3D的图形处理。
G. 如何将Bitmap位图与base64字符串相互转换
无论要对图片,还是mp3,还是电影文件,本质都是2进制串。所以你缺的不是位图到base64字符串的转换,而是一套Base64编码解码算法。
不清楚你的语言,以java为例。jdk1.8之前有api:Base64Encoder,Base64Decoder分别编码/解码。1.8除了更加厉害的 “Base64”。当然可以搜索各种各样的第三方jar包罗。
对于你这个文件处理需求,推荐这个:http://download.csdn.net/download/liuzhao2011/9963611。下载后,将java文件考项目中,调好包路径即可。大文件处理速度快,可以直接输出编码后的文件(代码中有例子)。使用方便无痛苦。
H. 怎么防止imagecreatefromjpeg内存溢出
尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
另外,以下方式也大有帮助:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 10; //width,hight设为原来的十分一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
以下奉上一个方法:
Java代码
1. /**
2. * 以最省内存的方式读取本地资源的图片
3. * @param context
4. * @param resId
5. * @return
6. */
7. public static Bitmap readBitMap(Context context, int resId){
8. BitmapFactory.Options opt = new BitmapFactory.Options();
9. opt.inPreferredConfig = Bitmap.Config.RGB_565;
10. opt.inPurgeable = true;
11. opt.inInputShareable = true;
12. //获取资源图片
13. InputStream is = context.getResources().openRawResource(resId);
14. return BitmapFactory.decodeStream(is,null,opt);
15. }
================================================================================
Android内存溢出的解决办法
转自:http://www.cppblog.com/iuranus/archive/2010/11/15/124394.html?opt=admin
昨天在模拟器上给gallery放入图片的时候,出现java.lang.OutOfMemoryError: bitmap size exceeds VM budget 异常,图像大小超过了RAM内存。
模拟器RAM比较小,只有8M内存,当我放入的大量的图片(每个100多K左右),就出现上面的原因。
由于每张图片先前是压缩的情况,放入到Bitmap的时候,大小会变大,导致超出RAM内存,具体解决办法如下:
//解决加载图片 内存溢出的问题
//Options 只保存图片尺寸大小,不保存图片到内存
BitmapFactory.Options opts = new BitmapFactory.Options();
//缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数,SDK中建议其值是2的指数值,值越大会导致图片不清晰
opts.inSampleSize = 4;
Bitmap bmp = null;
bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);
...
//回收
bmp.recycle();
通过上面的方式解决了,但是这并不是最完美的解决方式。
通过一些了解,得知如下:
优化Dalvik虚拟机的堆内存分配
对于Android平台来说,其托管层使用的Dalvik Java VM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体原理我们可以参考开源工程,这里我们仅说下使用方法: private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。
Android堆内存也可自己定义大小
对于一些Android项目,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对性能的影响十分敏感,除了 优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理
bitmap 设置图片尺寸,避免 内存溢出 OutOfMemoryError的优化方法
★android 中用bitmap 时很容易内存溢出,报如下错误:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget
● 主要是加上这段:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
● eg1:(通过Uri取图片)
private ImageView preview;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
Bitmap bitmap = BitmapFactory.decodeStream(cr
.openInputStream(uri), null, options);
preview.setImageBitmap(bitmap);
以上代码可以优化内存溢出,但它只是改变图片大小,并不能彻底解决内存溢出。
● eg2:(通过路径去图片)
private ImageView preview;
private String fileName= "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg";
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
Bitmap b = BitmapFactory.decodeFile(fileName, options);
preview.setImageBitmap(b);
filePath.setText(fileName);
★Android 还有一些性能优化的方法:
● 首先内存方面,可以参考 Android堆内存也可自己定义大小 和 优化Dalvik虚拟机的堆内存分配
● 基础类型上,因为Java没有实际的指针,在敏感运算方面还是要借助NDK来完成。Android123提示游戏开发者,这点比较有意思的是Google 推出NDK可能是帮助游戏开发人员,比如OpenGL ES的支持有明显的改观,本地代码操作图形界面是很必要的。
● 图形对象优化,这里要说的是Android上的Bitmap对象销毁,可以借助recycle()方法显示让GC回收一个Bitmap对象,通常对一个不用的Bitmap可以使用下面的方式,如
if(bitmapObject.isRecycled()==false) //如果没有回收
bitmapObject.recycle();
● 目前系统对动画支持比较弱智对于常规应用的补间过渡效果可以,但是对于游戏而言一般的美工可能习惯了GIF方式的统一处理,目前Android系统仅能预览GIF的第一帧,可以借助J2ME中通过线程和自己写解析器的方式来读取GIF89格式的资源。
● 对于大多数Android手机没有过多的物理按键可能我们需要想象下了做好手势识别 GestureDetector 和重力感应来实现操控。通常我们还要考虑误操作问题的降噪处理。
Android堆内存也可自己定义大小
对于一些大型Android项目或游戏来说在算法处理上没有问题外,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对性能的影响十分敏感,除了上次Android开发网提到的优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理,我们将在下次提到具体应用。
优化Dalvik虚拟机的堆内存分配
对于Android平台来说,其托管层使用的Dalvik JavaVM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体原理我们可以参考开源工程,这里我们仅说下使用方法: private final static floatTARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。
介绍一下图片占用进程的内存算法吧。
android中处理图片的基础类是Bitmap,顾名思义,就是位图。占用内存的算法如下:
图片的width*height*Config。
如果Config设置为ARGB_8888,那么上面的Config就是4。一张480*320的图片占用的内存就是480*320*4 byte。
前面有人说了一下8M的概念,其实是在默认情况下android进程的内存占用量为16M,因为Bitmap他除了java中持有数据外,底层C++的 skia图形库还会持有一个SKBitmap对象,因此一般图片占用内存推荐大小应该不超过8M。这个可以调整,编译源代码时可以设置参数。
I. bitmapfactory.decodefile是耗时操作吗
android 中用bitmap 时很容易内存溢出,报如下错误:Java.lang.OutOfMemoryError : bitmap size exceeds VM budget ● 主要是加上这段: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; ● eg1:(通过Uri取图片) private ImageView preview; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一 Bitmap bitmap = BitmapFactory.decodeStream(cr .openInputStream(uri), null, options); preview.setImageBitmap(bitmap); 以上代码可以优化内存溢出,但它只是改变图片大小,并不能彻底解决内存溢出。 ● eg2:(通过路径去图片) private ImageView preview; private String fileName= "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg"; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一 Bitmap b = BitmapFactory.decodeFile(fileName, options); preview.setImageBitmap(b); filePath.setText(fileName); ★Android 还有一些性能优化的方法: ● 首先内存方面,可以参考 Android堆内存也可自己定义大小 和 优化Dalvik虚拟机的堆内存分配 ● 基础类型上,因为Java没有实际的指针,在敏感运算方面还是要借助NDK来完成。Android123提示游戏开发者,这点比较有意思的是Google推出NDK可能是帮助游戏开发人员,比如OpenGL ES的支持有明显的改观,本地代码操作图形界面是很必要的。 ● 图形对象优化,这里要说的是Android上的Bitmap对象销毁,可以借助recycle()方法显示让GC回收一个Bitmap对象,通常对一个不用的Bitmap可以使用下面的方式,如 if(bitmapObject.isRecycled()==false) //如果没有回收 bitmapObject.recycle(); ● 目前系统对动画支持比较弱智对于常规应用的补间过渡效果可以,但是对于游戏而言一般的美工可能习惯了GIF方式的统一处理,目前 Android系统仅能预览GIF的第一帧,可以借助J2ME中通过线程和自己写解析器的方式来读取GIF89格式的资源。 ● 对于大多数Android手机没有过多的物理按键可能我们需要想象下了做好手势识别 GestureDetector 和重力感应来实现操控。通常我们还要考虑误操作问题的降噪处理。 Android堆内存也可自己定义大小 对于一些大型Android项目或游戏来说在算法处理上没有问题外,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对性能的影响十分敏感,除了上次Android开发网提到的 优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例: private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理,我们将在下次提到具体应用。 优化Dalvik虚拟机的堆内存分配 对于Android平台来说,其托管层使用的Dalvik JavaVM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体原理我们可以参考开源工程,这里我们仅说下使用方法: private final static floatTARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。