我们讲Android 优化 优化的点在哪
1 ,绘制优化
2,内存优化
3,存储优化
4,稳定性优化
5,耗电优化
6,apk包大小优化
绘制优化
先说说原理:
界面是每隔16ms 刷新一次 对图像进行栅格化渲染出来 如果大于16ms 才渲染出来 这就会让用户等到32ms 后才看到画面或者16ms的倍数 就会感觉卡 那关键什么原因导致渲染卡顿呐
导致渲染卡顿(绘制任务繁重耗时太长):
内存占用过高频繁gc
xml 界面过于复杂
如何优化:
关键是如何定位到该优化的点 需要借助工具
例如:查看Layout的层次的Hierarchy View
打开手机的辅助功能 GPU 渲染辅助功能
TraceView 分析内存
布局要优化:减少递归遍历的层次 (merge,viewStub 等)
使用 Lint 工具 可以为我们提出一些建议
避免过度绘制:有重叠的部分不要多次绘制 可以打开手机辅助工具进行检测
启动优化
在application MainActivity 中的一些方法中做处理
在使用Context 时 能使用的application 的就不要使用activity
优化的点: ui布局 绘制和数据准备
合理的刷新机制
避免后台线程影响:避免后台线程占用cpu过高
UI卡顿的监控
如何做 原理是什么:
我们都知道一个进程中只要一个MainLooper 在进行消息分发时会调用Handler中的dispatchMessage 方法 如果主线程卡顿了说明该方法内部出现问题 可以根据这个来做监控
如果有卡顿如何知道卡顿的点上报什么数据:
可以上报堆栈信息:卡顿时的堆栈信息
耗时信息,基本信息(系统版本,机型,进程名,版本号,磁盘空间)
//Looper 核心点
public void setMessageLogging(@Nullable Printer printer) {
mLogging = printer;
}
上报数据: 本身就卡了 先存到本地 先不要上报了等到空闲或者数据量可以了打包压缩上传到服务器
内存优化
有两个个点:
1,内存泄漏问题
2,优化内存空间
内存泄漏问题
内存为什么会泄漏: 对象不使用了但是不能被垃圾回收机制回收
如何检测到内存泄漏
使用工具进行检测 Memory Monitor 进行内存监控 提供了图像化的界面但不能精确到某个点导致的内存泄漏
HeapViewer 堆空间使用情况
Allocation Tracker :可以查找具体下泄漏点
内存泄漏如何监控
使用LeakCanary 默认情况下 它只对Activity进行监控
如果我们要对 Fragment BroadcastReceiver Service 进行监控怎么办
//可以在生命周期结束时调用该方法
LeakCanary.refWatcher(this).watchDelay(0, TimeUnit.MICROSECONDS);
自定义监控上传到可以上传到后台服务器
LeakCanary.refWatcher(this)
.listenerServiceClass(LeakCanaryService.class)
//LeakCanaryService 可以继承 DisplayLeakService
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
.buildAndInstall();
常见的泄漏场景
1,资源未关闭
2,注册对象未注销
3,类的静态变量持有大数据对象
4,非静态内部类的静态实例
5,Handler Context WebView 等常见对象
6,容器中的无用对象没有清理
优化内存空间
引用优化: 强 软 弱 虚 (弱 对有生命周期的 软 对长期存储内存中必要的时候可以释放掉的 虚 检测对象是否回收)
减少不必要的内存开销:如自动装箱问题 可以使用ArrayMap SparseArray LongSparseArray 等
内存复用:对象池,Bitmap 复用 视图复用 资源复用 LruCache
图片的优化:三级缓存(内存 , 本地 ,网络) 内存使用LruCache 缓存
图片显示优化:质量压缩,图片大小压缩 ,质量大小压缩 ,超级大图 分块显示
存储优化
序列化优化
没什么好说的 aidl 通信使用 Parcelable 相对字节小
如何是网络数据传输:可以使用Proto 相对字节小
SharedPreference优化
写入是不需要返回值使用 apply
避免频繁读写操作
数据库优化
1,使用 SQLiteStatement 在性能上有一定提高
2,使用事物 (原子提交 性能好)
3,使用索引 (数据量不大就不要用)
4, 可以使用双缓冲机制 (什么意思:常用的数据放到内存在异步更新到数库)
5,提高查询性能(查询数据量分页,减少查询数据的列数)
稳定性优化
我们说一个app 稳不稳定 主要看 是否崩溃,ANR
1,提高代码质量
如何提高: 看编码经验 和 通过工具进行检测是否合格
工具:Lint 阿里代码规范插件
2,Crash 监控
java 层监控
//当出现Crash 调用 先暂存到本地 下次在上传后台服务器
Thread.setDefaultUncaughtExceptionHandler();
native层监控
当程序Crash时 Linux 会生成dump文件 分析dump 可以找到原因
何时分析或者上传dump文件那: 当Linux Crash 会发信号 我们可以注册信号回调
#include <signal.h>
static int crash_signal[] = {
SIGILL,//执行了非法指令 堆栈溢出 可执行文件本身出错
SIGABRT,//调用了abort函数
SIGBUS,//访问非法地址
SIGFPE,//算数错误
SIGSEGV,//访问不属于自己的存储空间或访问只读存储空间
SIGPIPE //管道异常
};
static void JNICrashHandle(int n,siginfo_t *siginfo,void *sigcontext){
char *stacks = (char*)calloc(100, sizeof(char));
//dump 文件
}
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void * reserved ) {
struct sigaction act_crash;
memset(&act_crash,0, sizeof(act_crash));
act_crash.sa_sigaction = JNICrashHandle;
act_crash.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act_crash.sa_mask);
for(unsigned int i=0;i< sizeof(crash_signal)/ sizeof(crash_signal[0]);i++){
sigaction(crash_signal[i],&act_crash,NULL);
}
return JNI_VERSION_1_6;
}
上报到后台服务器
不要马上就上报 先存到本地 等下次启动在进行上报
3,ANR 监控
系统处理超时产生的ANR KeyDispatchTimeOut(5) BroadcastTimeOut(10) ServiceTimeOut(20)
根本原因:代码写的不好 有问题导致主线程堵塞 其他进程占用CPU过高(不考虑)
如何监控上报ANR:
和卡顿监控类似(UI卡顿的监控)
4,提高进程存活率
只考虑 系统通过回收内存杀掉进程
降低进程占用的内存(看内存优化)
提高进程优先极(网络连接心跳,利用系统机制:通知栏,注册系统广播,aidl 双进程 ,SyncAdapter)
<provider
android:authorities="xxxxxx"
android:name=".service.TestContentProvider"
android:syncable="true"/>
<!-- android:syncable="true" 为true -->
耗电优化
耗电的点在哪: 显示,CPU ,网络
优化的点:CPU,网络 上
网络 :
wifi: 尽量增大每个数据包大小
3G,4G: 最好批量执行网络请求,尽量避免频繁的间隔执行
传输数据包:json proto Gzip压缩
CPU:
减少运算量
使用 JobScheduler 削峰平谷
apk包大小优化
常用方案:
代码混淆 : 这个没什么好说的
资源优化:
尽量使用一套资源
SVG代替图片
移除无用的资源
压缩对齐 资源混淆和7zip压缩
可以使用微信团队开源的AndResGuard进行资源混淆
图片优化:对图个别大图片进行压缩 可以使用webp
lib: 使用 armeabi,armeabi-v7 就行
插件化:
放到服务器上减少包体积