Effect Android -项目优化与异常处理

项目优化

1.android 增量更新

效果:一个几百M的软件可能只需要下载一个20M的增量包就能完成更新
流程:下载了增量包,手机上的apk和增量包合并形成新的包,然后再次安装
具体:
1.用户手机上提取当前安装应用的apk
2.如何利用old.apk和new.apk生成增量文件 在服务端下发patch与md5值
3.增加文件与1.中的old.apk合并,然后安装 在应用内部合并

多渠道包:在本地合成时,将运行的apk拷贝出来后,去掉渠道号内容,然后再合成,得到的就是新的原始包,然后再追加相应的渠道号。

2.android 热修复


异常处理

1.ANR

定义

ApplicationNotResponding 应用未响应
应用在一段时间内无法响应用户交互事件
会弹出一个等待或者结束进程的对话框

原理

ActivityManager和WindowManager会定时检测组件状态
组件未在时间内响应则弹出ANR对话框
如:
Activity在5秒内无法响应屏幕触摸事件或键盘输入事件(定时检测)
在执行广播接收者的onReceive()函数时10秒没有处理完成,后台为60秒。
前台Service20秒内,后台服务在200秒内没有执行完毕。
内容提供者的publish函数在10s内没进行完。

产生原因

在主线程操作存在IO操作或者耗时计算

解决办法

异步执行耗时操作
避免在主线程 与各大组件生命周期内做耗时操作
避免死锁 (线程互相占有资源并等待对方释放)

2.OOM

定义

OutOfMemory 内存溢出

当前占有内存加上申请内存资源大小超过dalvik虚拟机最大内存限制
默认为64M

产生原因

加载图片占用了太多内存

解决办法

图片进行压缩

BitMap通过BitMapFactory创建对象时 会调用jni方法 占用一部分内存由java管理 一部分由c管理 java的gc会自动回收内存 而c的内存需要我们调用recycle()函数回收
所以需要及时释放C区内存

listview对图片进行复用 convertview lru缓存 最近最少使用

3.Android图片管理

Recycle源码

官方注解

调用recycle时会释放与bitmap相关联的原生对象同时清理对数据对象的引用(指针),调用后不会立即清理内存,只是给gc发送消息指令当确定其没有其他对象引用时回收,当执行此方法时 bitmap会被标记成dead状态,如果在调用其函数会导致异常,同时recycle操作不可逆,建议不要主动使用,gc会在bitmap没有引用时回收它

LRU

LRU是个泛型类 内部使用哈希链表存放键值对 提供对应的get put remove等基本操作
其中trimToSize函数 把用的最久的(map.eldest())缓存对象移除(map.remove(key))

三级缓存

内存缓存 采用LruCache 存储

本地硬盘缓存 以md5加密的url为文件地址 创建缓存图片 并压缩存储

网络缓存 从网络获取图片流 并由bitmapfactory decode生成bitmap对象

图片设置

计算合适的压缩比例 inSampleSize

BitmapFactory.Option配置
option.injustDecodeBounds
第一次injustDecodeBounds为true 只是把图片的宽高放在Options里
第二次injustDecodeBounds为false 再把图片读出来

4.UI卡顿

原理

Android进程每隔16ms触发UI渲染 若每次都成功 则会达到60fps的效果
若无法达到60fps 人眼会看出卡顿

原因分析

1.人为在UI线程中做轻微的耗时操作
2.布局layout过于复杂无法在16ms时完成渲染
3.同时间动画执行次数过多 导致gpu负载过重
4.view过度绘制 导致像素在同一帧绘制多次
5.view频繁触发ondraw onmeasure onlayout
6.gc执行频繁导致渲染被阻塞
7.冗杂资源和逻辑导致加载和执行缓慢

总结

1.布局优化 merge include
2.列表adapter优化
3.背景 图片 内存使用优化
4.避免 ANR

5.内存泄漏

JAVA内存泄漏

1.java内存分配策略

1.1.静态分配-静态存储区

主要存放静态数据、全局 static 数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。

1.2.栈式分配-栈区

栈内存-是系统自动分配空间的 char a
只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出

当方法被执行时,方法体内的局部变量(其中包括基础数据类型、对象的引用)都在栈上创建,并在方法执行结束时这些局部变量所持有的内存将会自动被释放

1.3.堆式分配-堆区

堆内存-程序员根据需要自己申请的空间 malloc(10)
首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆。

通常就是指在程序运行时直接 new 出来的内存,也就是对象的实例。这部分内存在不使用时将会由 Java 垃圾回收器来负责回收。

2.java如何管理内存

资源的创建和释放

Java使用有向图的方式进行内存管理,可以消除引用循环的问题
从根顶点深入引用 如果某个对象根顶点不可达 都是gc需要回收的目标

3.java中内存泄漏

内存泄漏指无用对象持续占用内存或无用对象得不到及时释放从而造成内存空间浪费的场景 称为内存泄漏

Android中内存泄漏的不恰当场景:

单例 :private Context mcontext;
构造函数传入context 若传入的是activity的上下文 会导致actvity无法被回收
应该 mcontext=getapplicationContext()跟整个app同步

匿名内部类和Thread:java中非静态内部类默认持有外部类引用 若外部类为activity
且内部类中有静态变量或者运行的线程 则会导致activity被引用无法被回收
(DVM) 会为所有活跃的threads在运行时系统中保持一个硬引用,也会导致threads一直处于运行状态
应当设置为静态内部类 并在合适的生命周期中关闭线程

Handler:
handler会一直looper messagequeue 若在activity 被销毁时而消息队列还有消息存在时handler与activity生命周期很难保证相同 经常会导致内存泄漏

正确写法

    private MyHandler myHandler=new MyHandler(this);
    private static class MyHandler extends Handler{
        private WeakReference reference;

        public MyHandler(WeakReference reference) {
            this.reference = reference;
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            BaseActivity activity= (BaseActivity) reference.get();
            if(activity!=null){

            }
        }
    }

6.冷启动优化

定义:
冷启动:在启动前 没有这个app对应进程的任何信息存在时
热启动:用户使用返回建退出应用 然后又马上重启

冷启动计算时间

冷启动流程

Zygote进程中fork创建出一个新的进程
创建和初始化Application类 创建第一个启动设置的Activity类
inflate布局 Activity构造方法 之后经过onMeasure-onDraw-onLayout 后显示界面

如何加快冷启动时间

1.减少onCreate方法工作量
2.不要让Application参与业务操作
3.不要让Application参与耗时操作
4.不要以静态变量方式在Application保存
5.尽量在布局中减少复杂度 嵌套层级尽量少
多使用include merge 标签 viewstub标签

7.其他优化

你可能感兴趣的:(Effect Android -项目优化与异常处理)