博客地址 :http://blog.csdn.net/w15321970103/article/details/76088905
内存优化
什么是OOM,OOM是如何造成的?
oom-out of memory(内存溢出), 当自身占用的内存加上要求分配的内存超过了系统给你的内存时, 系统就会抛出out of memory的异常(每个Android能用的内存是限的)比如: 当前应用只剩下4M的空间可用, 但你却加载得到一个需要占用5M空间的图片Bitmap对象, 就会抛出oom的异常
什么是内存泄漏,内存泄漏是如何造成的?
当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏
内存泄漏对程序的影响?
内存泄漏是造成应用程序OOM的主要原因之一!我们知道Android系统为每个应用程序分配的内存有限,
而当一个应用中产生的内存泄漏比较多时,这就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash
什么是内存抖动?
内存抖动可以看到内存的占用量短时间内大量被占用,短时间内又被大量释放,造成的原因变量短暂大量产生,又被大量释放,就会造成内存抖动,
什么是overDraw?
过度重绘:导致延迟绘制时间,做了很多无用功,消耗了内存
举例:在背景上加了背景颜色 在布局上又加了背景颜色
最后Button上又设置了颜色 那么重叠的部分就叫过度重绘
UI卡顿的原因?
一 首先我们要了解16ms黄金准则 : 一般来说,Android设备的屏幕刷新率为60帧每秒,要保持流畅就遇要每一帧不超过16.6MS每帧,如果超过就会发生跳帧的现象。
二 原因
- 1 人为在UI线程中做轻微耗时操作,导致UI线程卡顿
- 2 布局Layout过于复杂,无法在16ms内完成常渲染,view嵌套不建议超过8层
- 3 同一时间动画执行的次数过多,导致CPU或GPU负载过重
- 4 view过度绘制,导致某些像素在同一帧时间内被绘制多次,CPU或GPU负载过重
- 5 view频繁的触发measure layout 导致measure layout累计耗时过多及整个view频繁的重新渲染
- 6 内存频繁触发GC过多,导致暂时阻塞渲染操作
- 7 冗余资源及逻辑等导致加载和执行缓慢
- 8 频繁GC,GC所有线程会暂停
- 9 overDraw 重叠部分 绘制多次
如何内存优化?
- 1 布局优化 不要嵌套布局 不需要显示的布局要gone这样就不会绘制
- 2 列表及adapter优化 滑动停止再加载图片
- 3 背景和图片等内存分配优化
- 4 避免ANR
- 5 当service完成后,尽量关闭它
- 6 在UI不可见的时候,释放掉一些只有UI使用的资源
- 7 在系统内存紧张的时候,尽可能多的释放掉一些非重要资源
- 8 避免滥用Bitmap导致的内存泄漏
- 9 使用针对内存优化的数据容器
- 10 避免使用依赖注入的框架
布局优化
选用相对布局还是线性布局?
RelativeLayout : 在进行布局的时候会进行多次测量
嵌套越多测量次数越多
LinearLayout: 在设置权重的时候才会测量两次
相对布局可以让布局嵌套变少,而相对布局则测量少
所以最好的方式是结合使用
Merge和ViewStub的使用
- 1 尽量使用view自身的参数
- 2 减少一个布局的不必要节点(textView换行符替换多个textview,textView左右加图片属性等)
- 3 尽量重用一个布局文件(include包含重复的布局)
标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利
标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。
标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局想进度条、显示错误消息等可以使用
标签,以减少内存使用量,加快渲染速度。
是一个不可见的,大小为0的View。
标签使用如下
内存泄漏
android常见造成内存泄漏的问题是什么?
1 内存泄漏 是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,
从而造成的内存空间的浪费称为内存泄漏
2上下文导致的内存泄漏:举例 单例中持有的上下文是从activity传过来的,一旦activity不再需要,而被销毁的时候,因为单例的工具类还持有activity的引用,那么activity便不会被GC回收
3非静态内部类造成的内存泄漏 : 举例:(Handler造成的内存泄漏,AsyncTast内存泄漏等)当一个非静态内部类里做着一件耗时的任务,那么包含这个内部类的activity就算销毁也不回被回收。原因 非静态内部会持有外部类的引用(为什么会持有看下面)
4资源没有关闭造成的内存泄漏:如游标没有关闭 流没有关闭 bitmap没有释放等等
上下文导致内存泄漏的原因?
主要是GC原理,垃圾回收机制:Java采用根搜索算法,当GC Roots不可达时,并且对象finalize没有自救的情况下,才会回收。
回收对象:GC会收集那些不是GC roots且没有被GC roots引用的对象。
非静态内部类造成内存泄漏的原因?
1 静态内部类对外部类会存在一个隐式引用(因为非静态内部类可以调用外部类的方法,即然可以调用外部类的方法那么必须持有外部类的引用)
注意:内部类不一定会导致内存泄漏,除非执行了耗时任务外部类销毁的时候,
内部类的任务还在执行那么,执行的任务会持有内部类的引用,内部类又持有外部类的引用
public class BitmapDemo {
public void say(){
MyDemo demo = new MyDemo();
}
public void setName(){
}
class MyDemo{
public void say(){
setName();
}
}
}
2 静态内部类中存在异步任务,可能会导致其对应的外部类内存资源无法正常释放
3 静态内部类中创建了一个静态实例,会导致内存泄漏
解决方法
1 通过静态内部类来去除隐式引用
static class MyDemo{
public void say(){
//setName();
}
}
2 修改静态内部类的构造方式,手动引入其外部类引用(看handler内存泄漏解决)
3 Android可以WeakReference包裹外部类实例
handler如何造成内存泄漏?如何解决?
内存泄漏的原因:非静态内部类持有外部类的引用,当activity退出的时候有可能发送的message
还在message队列里,这样就造成外部引用被持有而不能被销毁。
解决办法
public class Main2Activity extends AppCompatActivity {
private MyHandler handler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
handler.sendEmptyMessage(1000);
}
static class MyHandler extends Handler{
private final SoftReference activitySoftReference;
public MyHandler(Activity activity){
activitySoftReference = new SoftReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (activitySoftReference != null){
}
}
}
}
什么是冷启动什么是热启动?
冷启动 :就是启动应用前,系统中没有该应用的任何进程信息(第一次启动应用,或者应用被杀死再次启动)
热启动 :用户使用返回键退出应用,然后马上又重新启动应用(进程是保留在后台的)
冷启动优化
- 1 减少onCreate方法的工作量 第三方在onCreate初始化懒加载()
- 2 不要让application参与业务的操作
- 3 不要在Application进行耗时操作
- 4 不要以静态变量的方式在application中保存数据
- 5 布局减少嵌套
sp问题
- 1 不能跨进程同步 每个进程都有一个副本
- 2 存储sp的文件过大问题
内存对象序列化
- serializeble 会产生大量的临时内存
- Parcelable 不能序列化硬盘上的文件而且使用繁琐
总结:
- 1 Serializeble是java的序列化方式,Parcelable是android特有的序列化方式
- 2 在使用内存的时候,Parcelable比Serializable性能高
- 3 Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC
- 4 parcelable不能使用在要将数据将存储在磁盘上的情况