参考: android开发艺术探索
1. 布局优化
不增加嵌套层级的情况下用LinearLayout代替RelativeLayout,
用include标签加载布局文件,merge标签和include一起使用减少布局层级;
ViewStub继承了View且宽高都是0,用来按需加载所需的布局文件,当调用它的setVisibility或者inflate方法加载后,ViewStub就会被它内部的布局替换掉;
拓展:
merge的作用是优化UI结构,合并重复的布局节点。
merge只能作为xml布局的根标签使用
2. 绘制优化
View的onDraw不要创建新的局部对象和进行大量的操作,不要做耗时任务,每一帧保持在16ms以内
3. 内存泄漏优化;
场景1 :静态变量持有外部变量(activity)导致内存泄漏
场景2 :单例导致的内存泄漏,单例我们一般写成静态的,注意使用Activity 的情况
场景3: 属性动画导致内存泄漏,注意必须在Activity 销毁的时候停止动画
场景4: Handler导致的内存泄漏
场景5 : 非静态内部类的静态实例的错误使用
场景6: 不正确使用线程,造成内存泄漏 由于创建线程时用到了Runnable 为匿名内部类,持有对外部类的引用,但是如果该外部类在销毁之前,线程中还有未完成的任务,这将导致该外部类无法被回收。
场景7 : 资源没有及时关闭
4.响应速度优化 和 ANR 分析
ANR的产生需要同时满足三个条件:
主线程:只有应用程序进程的主线程响应超时才会产生ANR;
超时时间:产生ANR的上下文不同,超时时间也不同,但只要超过这个时间上限没有响应就会产生ANR;
输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数调用。
产生ANR的上下文不同,导致ANR原因也不同,主要有以下三种情况:
应用进程的主线程对输入事件在5s内没有处理完毕;
应用进程的主线程在执行BroadcastRecevier的onReceive函数时10s内没有处理完毕;
应用进程的主线程在执行Service的各个生命周期函数时20s内没有处理完毕;
引起ANR的根本原因,总的来说可以归纳为两类:
- 应用进程自身引起的,比如:主线程阻塞、挂起、死循环,执行耗时操作等;
- 其他进程引起的,比如:其他进程CPU占用率过高,导致当前应用进程无法抢占到CPU时间片。常见的问题如文件读写频繁,io进程CPU占用率过高,导致当前应用出现ANR;
ANR解决方法
因为ANR主要是因为主线程由于耗时操作被阻塞而产生的,所以常见的解决方法是不在主线程做耗时操作,具体实现时需要注意以下几点:
· 主线程需要做耗时操作时,比如网络访问、数据库操作及位图变换等,必须启动一子线程处理,并利用handler来更新UI;
· 子线程尽量使用Android提供的API,比如HandlerThread,AsyncTask,AsyncQueryHandler等,这些API都提供了对于线程的系统级管理。如果应用直接使用Thread实现的话,则需要对这些子线程进行显式管理,比如线程池及线程周期的控制,以防止系统资源和内存泄漏;
· Broadcast Receiver中如果有耗时操作,可以放到service中来处理;
· 在后台子线程处理耗时操作时,为了提高用户体验,可以在前台界面显示某些动画或者progress bar;
5. ListView优化
主要是convertviwe复用,并在getview减少操作;根据滑动状态来选择性加载;开启硬件加速;
6. Bitmap优化
主要是通过BitmapFactory.Options对图片进行采样
7. 其他建议
1. 避免创建太多对象
2. 减少枚举使用
3. 常量使用static final 修饰
4. 使用Android 特有的数据结构
5. 软引用和若引用的使用
6. 内存缓存和磁盘缓存
7. 尽量使用静态内部类