liujiangchuan / liujiangchuan/BlogAndroidCN
Android内存优化总结(博客搬家)
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 1
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
### 以下内容本人于2015/04/02 20:34在“OhwYaa|东软知识社区”平台首发,现整理到个人博客中。原址仅内部公开:https://www.ohwyaa.com/neusoft.com/blog/50ab7b9d-5d7a-47d4-8c0b-00eb6d20c503/view/text
中国移动“和阅读”项目已启动5年多,我进入该项目组时是正在开发v3.0版本,项目的框架结构与基础功能已趋于稳定,随着客户不断提出新的需求,我们也在追求更高的标准和更优化的产品,为用户打造更时尚、便捷的随身阅读新体验。
随着新功能的不断设计和开发,业务逻辑逐渐复杂和庞大,对客户端性能也带来了极大的挑战,这使开发人员需要更加深入了解Android系统的特点及其优化方法。结合对项目的优化经验,在此做出总结与分享,分3个部分说明,分别为:布局优化、代码优化和图像优化。
**1. 布局优化**
(1) 抽象布局标签,使用,, 等标签进行布局;
(2) 减少嵌套层次,多使用RelativeLayout布局;
(3) 使用ListView缓存机制;
(4) 不要给布局写无用的参数,例如RelativeLayout,写layout_weight属性;
(5) 如果LinearLayout用于嵌套的layout空间计算,它的android:baselineAligned设置为false,可以加速layout计算;
(6) 尽量避免嵌套的使用layout_weight,那样会影响执行效率;
(7) 如果为rootView设置了背景,那么会先用Theme指定的背景绘制一遍,然后才用指定的背景绘制,这叫做"overdraw",可以通过theme的background为null来避免;
(8) 优化图片资源,尽量使用.9图片;
(9) 使用hierarchy viewer调优工具,查看布局measure、layout、draw的时间。
**2. 代码优化**
(1) 字符串拼接用StringBuilder代替String;
(2) 数据类型尽可能选择占用空间小的;
(3) 了解弱引用、虚引用;
(4) 优化算法,尽量不用递归;
(5) 尽量少的声明全局变量;
(6) 声明全局静态变量,一定要加final声明;
(7) 声明非静态的全局变量,最好不要初始化任何值,在使用到的地方,在进行初始化;
(8) 函数中若干次使用全局变量,应该将全局变量赋值给本地变量,然后直接使用本地变量;
(9) 能用Int,不要使用浮点数;
(10) 能用乘法不用除法,用位移更好;
(11) 尽量避免使用geter和setter方法;
(12) 在Activity的onCreate函数中,尽量做少的事;
(13) 在Activity中声明的静态数组或者静态代码块,重构到单独的一个类里;
(14) Activity启动后开始进行异步线程的加载,最好delay一下再开启线程;
(15) 对于存在于集合中的Bean对象,尽可能少的声明变量。能int就不要用long,声明的string等复杂变量,最好不要进行初始化;
(16) 使用线程,一定要给它传一个名字,然后需要定义线程的优先级;
(17) 在使用集合的时候,优先选择SparseArray,(代替HashMap)。Java 中每个类(包括匿名内部类)都占用至少 500字节左右的代码;每个类的实例会在 RAM 中占用大约 12 ~ 16 字节的内存;每向 HashMap 中添加一个 Entry 时,新生成的 Entry 占用大约 32 个字节;
(18) 尽量避免使用枚举,枚举类型 Enum 会比静态常量占用更多的内存;
(19) 工具方法尽量写成是静态方法;
(20) 线程间同步尽量使用开销小的同步锁;
(21) 在使用集合类的时候,如果已知数据的规模,在初始化的时候,就设定好默认大小;
(22) 私有内部类访问外部类的私有变量,要将变量修改为包继承权限;
(23) 对于开销大的算法,且不止是执行一次的,要使用缓存策略;
(24) 避免在绘制或者解析布局的时候,分配对象,例如onDraw方法;
(25) 用FloatMath代替Math;
(26) 记得关闭启动的服务;
(27) 当服务中的任务完成后,要记得停止该服务。可以考虑使用 IntentService,因为IntentService 在完成任务后会自动停止;
(28) UI不可见时释放资源;
(29) 在 onStop 中关闭网络连接、注销广播接收器、释放传感器等资源;
(30) 在 onTrimMemory() 回调方法中监听TRIM_MEMORY_UI_HIDDEN级别的信号,此时可在 Activity 中释放 UI 使用的资源,大符减少应用占用的内存,从而避免被系统清除出内存。内存紧张时释放资源。另:尽管系统主要按照 LRU 中顺序来杀进程,不过系统也会考虑程序占用的内存多少,那些占用内存高的进程有更高的可能性会被首先杀死;
(31) 确定你的程序应该占用多少内存,可以通过getMemoryClass()来获取你的程序被分配的可用内存,以 M 为单位。你可以通过在 标签下将 largeHeap 属性设为 true 来要求更多的内存,这时通过 getLargeMemoryClass() 方法来获取可用内存。大部分应用程序不需要使用此功能,因此使用该标签前,确认你的程序是否真的需要更多内存。使用更多内存会对整个系统的性能产生影响,而且当程序进入 LRU时会更容易首先被系统清理掉;
(32) 谨慎使用第三方类库;这些外部类库可能原先并非针对移动平台,因此未进行过优化,在使用前应注意。另外尽量不要因为一两个特性而使用一个体积很大的类库;
(33) 使用 ProGuard 移除无用的代码并重命名一些类、字段、方法等,使你的代码更紧凑,节省内存空间;
(34) 使用多个进程。如果程序需要执行大量的后台工作,可考虑将程序分为两个进程,一个进程负责 UI,另一个进程负责后台任务。比如音乐播放器。在决定是否使用多进程前,应注意,一个不执行任何任务的空进程至少也要占用 1.4 MB内存。另外要注意进程的相互依赖性,比如如果将ContentProvider 放在 UI 进程中,而后台任务进程也需要调用 ContentProvider,就会导致 UI 进程一直保留在 RAM 中。
**3. 图像优化**
图片资源的使用不当经常会造成OOM的问题,尤其在低端机型内存较少的情况下。
(1) 及时回收。
正确使用 Bipmap,避免浪费内存;调用recycle方法主动回收资源。代码示例:
```
if(null != bitmap && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap= null;
}
```
(2) 适当压缩。
如果你的ImageViwe 的尺寸只有50 * 50,那么没有必要将一张1280 * 720 的图片整个加载入内存;对图片进行适当的压缩。代码示例:
```
BitmapFactory.OptionsnewOpts = newBitmapFactory.Options();
newOpts.inPreferredConfig= Config.RGB_565;
newOpts.inJustDecodeBounds= true;
Bitmapbitmap = BitmapFactory.decodeFile(srcPath,newOpts);
newOpts.inJustDecodeBounds= false;
intold_w = newOpts.outWidth;
intold_h = newOpts.outHeight;
intnew_w = targetWidth;
intnew_h = targetHeight;
intbe = (int) ((old_w / new_w + old_h /new_h) >> 1);
if(be <= 1) {
be= 1;
}
newOpts.inSampleSize= be;
bitmap =BitmapFactory.decodeFile(srcPath,newOpts);
```
本项目经过一轮仔细的优化后,在测试机上,内存占用情况从平均68.5M降低到平均48.5M,有明显的优化效果。优化是一个需要持之以恒要去完善的任务,希望每个开发者都对性能优化有所了解,在开发过程中除了实现需求和功能之外,多去思考如何写出更漂亮的代码,为项目锦上添花。
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue body contains the full Android memory-optimization article and links to its original internal publication. Start by comparing that source with the intended blog location; the issue does not name a target file, test, or specific missing change. Done would require a clearly identified publication or content-update scope, which is not stated here.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java
- Domain
- content, documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100