在Android中,应用的响应性被活动管理器(ActivityManager)和窗口管理器(Window Manager)这两个系统服务所监视。当用户触发了输入事件(如键盘输入,点击按钮等),如果应用5秒内没有响应用户的输入事件,那么,Android会认为该应用无响应,便弹出ANR对话框。而弹出ANR异常,也主要是为了提升用户体验。
解决方案是对于耗时的操作,比如访问网络、访问数据库等操作,需要开辟子线程,在子线程处理耗时的操作,主线程主要实现UI的操作。
关于内存泄漏,一般像单例模式的使用不当、集合的操作不当、资源的缺乏有效的回收机制、Handler、线程的使用不当等等都有可能引发内存泄漏。
原因:
1、降低Overdraw(过度绘制),减少不必要的背景绘制
2、减少嵌套层次及控件个数
3、使用Canvas的clipRect和clipPath方法限制View的绘制区域
4、通过imageDrawable方法进行设置避免ImageView的background和imageDrawable重叠
5、借助ViewStub按需延迟加载
6、选择合适的布局类型
7、熟悉API尽量借助系统现有的属性来实现一些UI效果
这是最基本的一条规则,但非常重要。
对于绝大对数APP来说,只需要取一套设计图就足够了。
鉴于现在分辨率的趋势,建议取720p的资源,放到xhdpi目录。
相对于多套资源,只使用720P的一套资源,在视觉上差别不大,很多大公司的产品也是如此,但却能显著的减少资源占用大小,顺便也能减轻设计师的出图工作量了。
注意,这里不是说把不是xhdpi的目录都删除,而是强调保留一套设计资源就够了。
在gradle使用minifyEnabled进行Proguard混淆的配置,可大大减小APP大小:
android {
buildTypes {
release {
minifyEnabled true
}
}
}
在proguard中,是否保留符号表对APP的大小是有显著的影响的,可酌情不保留,但是建议尽量保留用于调试。
详细proguard的相关的配置和原理可自行查阅。
在gradle使用shrinkResources去除无用资源,效果非常好。
android {
buildTypes {
release {
shrinkResources true
}
}
}
大部分应用其实并不需要支持几十种语言的国际化支持。
还好强大的gradle支持语言的配置,比如国内应用只支持中文:
android {
defaultConfig {
resConfigs "zh"
}
}
android打包本身会对png进行无损压缩,所以使用像Tinypng这样的有损压缩是有必要的。
重点是Tinypng使用智能有损压缩技术,以尽量少的失真换来图片大小的锐减,效果非常好,强烈推荐。
Tinypng的官方网站:TinyPNG – Compress WebP, PNG and JPEG images intelligently
如果对于非透明的大图,jpg将会比png的大小有显著的优势,虽然不是绝对的,但是通常会减小到一半都不止。
在启动页,活动页等之类的大图展示区采用jpg将是非常明智的选择。
webp支持透明度,压缩比比jpg更高但显示效果却不输于jpg,官方评测quality参数等于75均衡最佳。
相对于jpg、png,webp作为一种新的图片格式,限于android的支持情况暂时还没用在手机端广泛应用起来。从Android 4.0+开始原生支持,但是不支持包含透明度,直到Android 4.2.1+才支持显示含透明度的webp,使用的时候要特别注意。
官方介绍
如果经过上述步骤之后,你的工程里面还有一些大图,考虑是否有必要维持这样的大尺寸,是否能适当的缩小。
事实上,由于设计师出图的原因,我们拿到的很多图片完全可以适当的缩小而对视觉影响是极小的。
有些第三库里引用了一些大图但是实际上并不会被我们用到,就可以考虑用1x1的透明图片覆盖。
你可能会有点不舒服,因为你的drawable下竟然包含了一些莫名其妙的名称的1x1图片…
基本上armable的so也是兼容armable-v7的,armablev7a的库会对图形渲染方面有很大的改进,如果没有这方面的要求,可以精简。
这里不排除有极少数设备会Crash,可能和不同的so有一定的关系,请大家务必测试周全后再发布。
与第十条不同的是,x86包下的so在x86型号的手机是需要的,如果产品没用这方面的要求也可以精简。
建议实际工作的配置是只保留armable、x86下的so文件,算是一个折中的方案。
微信资源压缩打包工具通过短资源名称,采用7zip对APP进行极致压缩实现减小APP的目标,效果非常的好,强烈推荐。
详情参考:Android资源混淆工具使用说明
原理介绍:安装包立减1M–微信Android资源混淆打包工具建议开启7zip,注意白名单的配置,否则会导致有些资源找不到,官方已经发布AndResGuard到gradle中了,非常方便:
apply plugin:'AndResGuard'
buildscript {
dependencies {
classpath 'com.tencent.mm:AndResGuard-gradleplugin:1.1.7'
}
}
andResGuard {
mappingFile = null
use7zip = true
useSign = true
keepRoot = false
// add < your_application_id >.R.drawable.icon into whitelist.
// because the launcher will get thgge icon with his name
def packageName = whiteList = [
//for your icon
packageName + ".R.drawable.icon",
//for fabric
packageName + ".R.string.com.crashlytics.*",
//for umeng update
packageName + ".R.string.umeng*",
packageName + ".R.string.UM*",
packageName + ".R.string.tb_*",
packageName + ".R.layout.umeng*",
packageName + ".R.layout.tb_*",
packageName + ".R.drawable.umeng*",
packageName + ".R.drawable.tb_*",
packageName + ".R.anim.umeng*",
packageName + ".R.color.umeng*",
packageName + ".R.color.tb_*",
packageName + ".R.style.*UM*",
packageName + ".R.style.umeng*",
packageName + ".R.id.umeng*"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.1.7'
//path = "/usr/local/bin/7za"
}
}
会生成一个andresguard/resguard的Task,自动读取release签名进行重新混淆打包。
对于一些库是按照需要动态的加载,可能在某些版本并不需要,但是代码又不方便去除否则会编译不过。
使用provided可以保证代码编译通过,但是实际打包中并不引用此第三方库,实现了控制APP大小的目标。
但是也同时就需要开发者自己判断不引用这个第三方库时就不要执行到相关的代码,避免APP崩溃。
特别是在扁平化盛行的当下,很多纯色的渐变的圆角的图片都可以用shape实现,代码灵活可控,省去了量的背景图片。
相信你的工程里也有很多selector文件,也有很多相似的图片只是颜色不同,通过着色方案我们能大大减轻这样的工作量,减少这样的文件。
借助于android support库可实现一个全版本兼容的着色方案,参考代码:DrawableLess.java
如果你的APP支持素材库(比如聊天表情库)的话,考虑在线加载模式,因为往往素材库都有不小的体积。
这一步需要开发者实现在线加载,一方面增加代码的复杂度,一方面提高了APP的流量消耗,建议酌情选择。
避免重复库看上去是理所当然的,但是秘密总是藏的很深,一定要当心你引用的第三方库又引用了哪个第三方库,这就很容易出现功能重复的库了,比如使用了两个图片加载库:Glide和Picasso。
通过查看exploded-aar目录和External Libraries或者反编译生成的APK,尽量避免重复库的大小,减小APP大小。
同样功能的库在大小上是不同的,甚至会悬殊很大。
如果并无对某个库特别需求而又对APP大小有严格要求的话,比较这些相同功能第三方库的大小,选择更小的库会减小APP大小。
过去的一年,插件化技术雨后春笋一样的都冒了出来,这些技术支持动态的加载代码和动态的加载资源,把APP的一部分分离出来了,对于业务庞大的项目来说非常有用,极大的分解了APP大小。
因为插件化技术需要一定的技术保障和服务端系统支持,有一定的风险,如无必要(比如一些小型项目,也没什么扩展业务)就不需要了,建议酌情选择。
这条完全取决于业务需求。
从统计数据分析砍掉一些没用的功能是完全有可能的,甚至干脆去掉一些花哨的功能出个轻聊版、极速版也不是不可以的。
多次执行上述步骤,你总能发现一些蛛丝马迹,这是一个好消息,不是吗?
redex是facebook发布的一款android字节码的优化工具,需要按照说明文档自行配置一下。
redex input.apk -o output.apk --sign -s -a -p
上面都是easy的做法
开启混淆
优化方案总结
使用要谨慎,如精确度不高可用WiFi定位或者基站定位,可用
非要用的话,注意定位数据的复用和定位频率的阈值
按需启动,用完就退出
减少网络网络请求次数和数据量
WiFi比手机网络省电
减少I/O操作(包括数据库操作)
减少大量的计算
使用频率优化和选择低功耗模式
首先我们 要知道Bitmap内存是怎么计算的例子:
手机屏幕大小 1080 x 1920(inTarget = 420),加载xhdpi (inDensity = 320)中的图片 1920 x 1080,scale = 420 / 320,最总我们可以得知他的占用内存 1418 * 2520 * 4 很明显 被放大了。