性能优化系列阅读
内存优化
1-内存的管理机制
2-常见问题
3-Memory Monitor工具使用
4-内存抖动案例及优化
5-利用Allocation Tracker查找内存抖动中有问题的代码
6-利用Heap Viewer监控内存泄漏
7-利用AS中的Heap Viewer查看内存泄漏原因
8-AS中的Heap Viewer展示信息说明
9-利用LeakCanary工具监控内存泄漏
10-利用LeakCanary工具监控应用市场项目中的内存泄漏
11-Handler内存泄漏原因分析
12-内存碎片问题展示
13-使用对象池优化内存碎片问题
界面卡顿优化
1-什么是卡顿
2-卡顿产生的原因分析-Profile GPU Rendering工具使用
3-卡顿产生的原因分析-渲染流程讲解
4-过渡绘制及优化
5-分析自定义控件的过渡绘制
6-解决自定义控件的过渡绘制
7-层级查看器的使用
8-界面优化常用做法
9-Lint可以查找那些代码问题
10-使用Lint进行代码问题的查找
11-Traceview工具使用
12-Traceview案例分析
13-减少CPU主线程占用时间的常规做法
14-综合案例编写
15-综合案例优化步骤
16-使用IntentService处理掉Application中的初始化工作
17-应用异常处理
18-过渡绘制
19-优化布局层级
20-Launch screens设置
网络优化
1-什么是网络优化
2-网络优化工作流程
3-网络监控工具使用
4-通信数据优化
5-为什么需要批量处理请求
6-如何进行批量处理请求
7-预取数据
8-预取数据案例
9-网络状态管理
10-案例_网络类型判断
11-案例_主动获取新闻
12-案例_获取新闻详情
13-案例_定时器使用(AlarmManager)
14-案例_定时器使用(JobScheduler)
15-案例_批量上传数据
16-案例_SyncAdater框架
17-SyncAdapter使用_创建SyncAdapter类
18-SyncAdapter使用_创建SyncService类
19-SyncAdapter使用_账户创建
20-SyncAdapter使用_触发SyncAdapter
电量优化
1-手机系统对应用的电量监控
2-使用Battery Historian查看电量监控数据
3-电量报表数据查看
4-应用电量分布情况
5-通用电量优化方案
6-常用API介绍
7-Doze模式
8-App Standby模式
内存泄露
内存泄露是指对象已经不再使用,但是因为某种原因还存在于内存中,没有及时地被垃圾回收器(GC)回收,从而造成了内存溢出
导致内存溢出的最主要的原因就是某些长存对象持有了一些其它应该被回收的对象的引用,导致垃圾回收器无法去回收这些对象,那也就出现内存泄露了。或者说是长生命周期对象持有了短生命周期对象的引用就很可能发生内存泄露
监测内存泄露的工具
- Leakcanary
内存泄露监测神器,出自著名的开源组织square - Eclipse Analysis Memory Tools(MAT)
Eclipse的内存分析工具 - dumpsys meminfo命令
- ddms的heap内存监测工具
- Android studio Monitors
在该监听器下有图形化的分析工具,memory,cpu,gpu,network
内存溢出
垃圾回收
java中用有向图表示引用关系,可达,存在连接通路,不可达
GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请,引用,被引用,复制等,GC都要进行监控
java的内存管理就是对象的分配和释放问题,在java中,程序员需要通过关键字new为每个对象申请内存空间(基本数据类型除外),所有的对象都在堆heap中分配空间,另外对象的释放是由GC决定和执行的,在java中,内存的分配是有程序完成的,而内存的释放是由GC来完成的,这种收支两条线的方法确实减少了程序员的工作,但同时它也加重了JVM的工作,这也是java运行速度较慢的原因之一。因为GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请,引用,被引用,复制等,GC都需要进行监控
监控对象状态是为了更加准确,及时的释放对象,而释放对象的根本原则就是该对象不再被引用
GC的工作原理
为了更好理解 GC 的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从 main 进程开始执行,那么该图就是以 main 进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被 GC 回收。 以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。
Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。
内存管理
从上图可以看出,java内存区域主要分为2部分
- 线程共享内存区:java堆,方法区
- 线程私有内存区:虚拟机栈,本地方法栈,程序计数器,这部分内存是随着线程的产生二产生,消亡而消亡,因此不需要过多的考虑内存回收的问题,编译时就已经确定所需内存的大小
1、栈
对象的引用,数组的引用
2、堆
new出来的对象,数组
3、方法区
类信息,常量(常量池),静态变量
Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池(Class文件常量池),用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
4、程序计数器
一块较小的内存空间,它是当前线程所执行的字节码的行号指示器,字节码解释器工作时通过改变计数器的值来选择下一条需要执行的字节码指令,分支,跳转,循环等基础功能都要依赖它来实现。每条线程都有一个独立的程序计数器,各个线程间的计数器互不影响,因此该区域是线程私有的
内存分配策略
java程序运行时的内存分配策略有三种,分别是静态分配,栈式分配和堆式分配,对应的三种存储策略使用的内存空间分别是静态存储区(也叫方法区),栈区和堆区。
1、静态存储区(方法区)
主要存放静态数据,全局static数据和常量,这块内存在编译时就已经分配好,并且在程序整个运行期间都会存在
2、栈区
当方法被执行时,方法内部的局部变量(其中包括基本数据类型和对象的引用)都在栈上创建,并在方法执行结束的时候这些局部变量所持有的内存都将自动被释放。因为栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量很有限
栈还分配堆中对象或数组的引用内存空间
3、堆区
又称为动态内存分配,通常就是指程序运行时直接new出来的内存,也就是对象的实例,数组,这部分内存在不使用时将由java垃圾回收器来负责回收
JVM
电量优化
布局优化
性能优化
1、使用IntentService
使用IntentService有两个好处,一个是任务执行完的时候,IntentService会自动结束,不会像Service那样长期呆在后台;另外一个是不需要手动开辟子线程去执行耗时操作,因为IntentService已经帮我们做了这些工作
2、使用优化的数据容器
- SparseArray稀疏数组,替代HashMap
- SparseBooleanArray 替代HashMap
- LongSparseArray
- ArrayMap
3、使用线程池管理线程
在需要开辟子线程去执行耗时任务的时候不要通过new Thread的方式,因为创建和销毁一个线程所消耗的资源可能会比执行这个线程所消耗的资源更多,所以我们应该使用线程池技术,去统一的管理和缓存线程,提高效率
4、优化Bitmap
内存溢出大部分情况都是大图片导致的,大图片占用的内存是像素总数x每个像素占用的字节数,一张很小的图片都有可能占用很大的内存,所以我们很有必要对图片进行压缩,缓存图片(三级缓存),复用Bitmap(inBitmap属性),回收Bitmap(recycle())