一.布局优化
布局优化的本质就是减少View的层级。
在LinearLayout和RelativeLayout都可以完成布局的情况下优先选择LinearLayout,可以减少View的层级,但是注意相同组件可能RelativeLayout绘制时间长
使用 < include > 标签将常用的布局组件共同的部分抽取出来,以便复用。
使用ConstraintLayout 减少层级 ConstraintLayout支持构建复杂的页面布局,如果使用它作为页面的布局容器,基本上一层就足够了
二.绘制优化
1.onDraw中不要创建新的局部对象。
2.onDeraw中不做耗时的任务
三.网络优化
-
大量数据的加载采用分页的方式
-
网络数据传输采用GZIP压缩
-
加入网络数据的缓存,避免频繁请求网络
-
上传图片时,在必要的时候压缩图片
四.安装包优化
减少应用中不必要的资源文件,比如图片,在不影响APP效果的情况下尽量压缩图片,有一定的效果
五.Android内存优化
1.Android内存管理机制
Android应用都是在Android虚拟机上运行的,内存分配和垃圾回收都是由Android虚拟机来完成的。
2.常见的内存泄漏
其实内存泄漏的本质就是较长生命周期的对象引用了较短生命周期的对象。
2.1 内存泄露
内存泄漏原因:堆上分配的对象已经不会再使用,但是GC收集器无法对其进行回收,此对象被强应用所引用 。
静态变量导致的内存泄漏
解决办法:将内部类设为静态内部类或独立出来;使用context.getApplicationContext()。
单例模式导致的内存泄漏
解决办法:传参context.getApplicationContext()。
属性动画导致的内存泄漏
解决办法:在Activity.onDestroy()中调用Animator.cancel()停止动画。
Handler导致的内存泄漏
解决办法:使用静态内部类+WeakReference弱引用;当外部类结束生命周期时清空消息队列。
线程导致的内存泄漏
解决办法:将AsyncTask和Runnable设为静态内部类或独立出来;在线程内部采用弱引用保存Context引用。
资源未关闭导致的内存泄漏
解决办法:在Activity销毁的时候要及时关闭或者注销。例如:
① BraodcastReceiver:调用unregisterReceiver()注销;
②Cursor,Stream、File:调用close()关闭;
③Bitmap:调用recycle()释放内存(2.3版本后无需手动)。
Adapter导致的内存泄漏
详情:不使用缓存而只依靠getView() 每次重新实例化Item,会给gc制造压力。
解决办法:在构造Adapter时使用缓存的convertView。
WebView导致的内存泄漏。
详情:WebView比较特殊,即使是调用了它的destroy方法,依然会导致内存泄漏。
解决办法:其实避免WebView导致内存泄漏的最好方法就是让WebView所在的Activity处于另一个进程中,当这个Activity结束时杀死当前WebView所处的进程即可,我记得阿里钉钉的WebView就是另外开启的一个进程,应该也是采用这种方法避免内存泄漏。
集合类泄漏
详情:比如全局map等有静态应用,最后没有做删除。
解决办法:在onDestry时回收不需要的集合。
2.2 扩大内存
大厂的SDK可能内存泄漏会少一些,但一些小厂的SDK质量也就不太靠谱一些。那应对这种我们无法改变的情况,最好的办法就是扩大内存。
扩大内存通常有两种方法:
一个是在清单文件中的Application下添加largeHeap="true"这个属性,另一个就是同一个应用开启多个进程来扩大一个应用的总内存空间。
第二种方法其实就很常见了,比方说我使用过个推的SDK,个推的Service其实就是处在另外一个单独的进程中。
Android中的内存优化总的来说就是开源和节流,开源就是扩大内存,节流就是避免内存泄漏。
2.3 检测、分析内存泄漏的工具
MemoryMonitor:随时间变化,内存占用的变化情况
MAT:输入HRPOF文件,输出分析结果
a. Histogram:查看不同类型对象及其大小
b.DominateTree:对象占用内存及其引用关系
c.MAT使用教程
LeakCanary:实时监测内存泄漏的库(LeakCanary原理)
六.卡顿优化方案
-
不要在主线程进行网络访问/大文件的IO操作
-
合理的刷新机制,尽量减少刷新次数,尽量避免后台有高的 CPU 线程运行,缩小刷新区域
七.耗电优化
合理的使用wake_lock锁,wake_lock锁主要是相对系统的休眠(这里就是为了省电,才做休)而言的,意思就是我的程序给CPU加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。有的情况如果不这么做就会出现一些问题,比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。所以微信里面是有大量使用到了wake_lock锁。
使用jobScheduler2,集中处理一些网络请求,有些不用很及时的处理可以放在充电的时候处理,比如,图片的处理,APP下载更新等等;