APK资源占用情况分析: Android Studio工具栏中,打开build–>Analyze APK,选择要分析的APK包
APK分析页面如下:
res: 用来存放资源文件,会自动生成对应的 ID 并映射到 .R 文件中,访问直接使用资源 ID
classes.dex: Dalvik 字节码程序,Dalvik虚拟机执行文件,一般情况下,Android 应用在打包时通过 Android SDK 中的 dx 工具将 Java 字节码转换为 Dalvik 字节码
META-INF: 保存应用的签名信息,签名信息可以验证 APK 文件的完整性
resources.arsc: 记录着资源文件和资源 ID 之间的映射关系,用来根据资源 ID 寻找资源
AndroidManifest.xml: 记录Android 应用的配置信息,如:四大组件的注册信息和权限配置信息等
1.清理不必要的资源
根据现在手机的分辨率,只需要设计一套适合大众的分辨率的资源图片如:720P.
Android Studio工具栏中,打开Refactor->Remove Unused Resources
清除重复的库和冗余代码
合理放置资源文件
应用图标优先放在mipmap目录下(AndroidStudio环境),其他资源图 .9图应该放在drawable-xxxx下,需要复制到手机sd卡上使用的应放在asset目录中
2.代码混淆
gradle中使用minifyEnabled进行Proguard混淆的配置
android {
buildTypes {
release {
minifyEnabled true
}
}
}
3.图片优化
可以对jpeg和PNG的压缩图处理.瘦身后分辨率不变,格式不变; 肉眼画质不变; 图片体积大幅减少,节省内存
Tinypng:http://tinypng.com/
七牛云: https://portal.qiniu.com/dora/fop/imageslim
如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止
在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择
矢量图
矢量图是由点与线组成,和位图不一样,它再放大也能保持清晰度,而且使用矢量图比位图设计方案能节约30~40%的空间,现在谷歌一直在强调扁平化方式,矢量图可很好的契合该设计理念。
—优势
(1)占用存储空间小
(2) 无极拉伸不会出现锯齿,可以照顾不同尺寸的机型
(3)Android Studio自带很多资源,减小UI工作量
—劣势
(1) 只支持5.0及以上系统
(2) 与位图相比多了一层计算,需消耗更多性能
(3) 不支持.9图
(4)不适合表现真实照片和复杂图形,一般使用在简单的icon和动画上
使用shape背景
特别是在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了大量的背景图片
1.Launcher中点击启动程序,通知ActivityManagerService
2.ActivityManagerService通知zygote进程孵化出应用进程,分配内存空间等
3.执行该应用ActivityThread的main()方法
4.应用程序通知ActivityManagerService 它已经启动,ActivityManagerService保存一个该应用的代理对象,ActivityManagerService通过它可以控制应用进程
5.ActivityManagerService通知应用进程创建入口的Activity实例,执行它的生命周期
启动过程中Application和入口Activity的生命周期方法按如下顺序调用:
1.Application 构造方法
2.attachBaseContext()
3.onCreate()
4.入口Activity的对象构造
5.setTheme() 设置主题等信息
6.入口Activity的onCreate()
7.入口Activity的onStart()
8.入口Activity的onResume()
9.入口Activity的onAttachToWindow()
10.入口Activity的onWindowFocusChanged()
从上可以看出,APP的启动与Application和Activity有直接的关系,因此优化的点也是由这两个类展开
查看冷启动耗时 方式一:
API19之后,Android系统Log中增加了Display的Log信息,通过过滤ActivityManager或Display关键字,可以获取APP启动的时间.
> ActivityManager: Displayed com.qihoo.appstore/.home.MainActivity: +2s541ms (total +6s438ms)
查看冷启动耗时 方式二:
adb shell am start -W [PackageName]/[PackageName.MainActivity]
C:\Users\ansen>adb shell am start -W com.android.documentsui/android.apps.activitys.FileMainActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.documentsui/android.apps.activitys.FileMainActivity }
Status: ok
Activity: com.android.documentsui/android.apps.activitys.FileMainActivity
ThisTime: 186
TotalTime: 186
WaitTime: 225
Complete
知道启动时间之后接下来就是优化方向
1.避免在Application和Activity的启动生命周期方法中做耗时的初始化逻辑,可以把这些逻辑放在异步线程中或延迟执行(主要有一些三方sdk的初始耗时问题).
Application是程序的主入口,Activity是UI的主入口.正因如此,我们的初始化操作几乎都在此.
所以这里的耗时会直接影响APP启动时间.
2.避免启动页UI的过度绘制,减少UI重复绘制时间(打开设置中的GPU过度绘制开关,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一)
3.系统加载一个activity之前,为了较好的体验,会先绘制一些初始化界面windowBackground.可以用一个.9图片替换掉替换首次启动的黑屏或白屏问题
上面有说到不要在初始化的过程中做耗时的逻辑,那初始化代码很多,怎么检测每个方法执行了多长时间呢?
Traceview
Android Device Monitor中使用:
启动应用,点击 Start Method Tracing,应用启动后再次点击,会自动打开刚才操作所记录下的.trace文件,
建议使用DDMS来查看,功能更加方便全面
代码中使用:
1.在onCreate开始和结尾打上trace
Debug.startMethodTracing("ansen");
// 需要检测的代码逻辑
Debug.stopMethodTracing();
注意加读写权限
程序运行起来,会在sdcard生成一个ansen.trace的文件
2.导出文件,使用DDMS分析trace文件
adb pull /sdcard/ansen.trace ~/temp
打开trace文件后:
在下方的方法区点击"Real Time/Call",按照方法每次调用耗时降序排.
Systrace
在onCreate方法里面添加trace.beginSection()与trace.endSection()方法来声明需要跟踪的起止位置,系统会帮忙统计中间经历过的函数调用耗时,并输出报表.
APP卡顿16ms原则:
Android系统每隔16ms会发出VSYNC信号重绘我们的界面(Activity).
为什么是16ms, 因为Android设定的刷新率是60FPS(Frame Per Second), 也就是每秒60帧的刷新率, 约合16ms刷新一次
定位问题:避免I/O操作、反序列化、网络操作、布局嵌套等
相关链接直达:
Android APP性能优化之 ---- 布局优化(一)
Android APP性能优化之 ---- 内存优化(二)
Android APP性能优化之 ---- 代码优化(三)
Android APP性能优化之 ---- 优化监测工具(四)
Android APP性能优化之 ---- APK瘦身 App启动优化
Android内存泄露OOM的原因及解决方法