Android优化

Android性能优化:

一、性能检测工具

(一)网易开源的Emmagee  https://github.com/NetEase/Emmagee 

Emmagee(机关枪)是网易杭州研究院QA团队开发的一个简单易上手的Android性能监测小工具,主要用于监控单个App的CPU,内存,流量,启动耗时,电量,电流等性能状态的变化,且用户可自定义配置监控的频率以及性能的实时显示,并最终生成一份性能统计文件。

使用步骤:

1、在GitHub下载安装包Apk

2、运行Emmagee.app。可以设置采集频率。     

3、点击APP"测试报告"查看,也可以配置邮件下发CSV文件。而我选择盗取文件到电脑上用Excel表格看。

(本地内部存储Emmagee目录”storage\sdcard0\Emmagee\某日期时间_APP包名.csv”的文件,即为监控数据)
 

(二)腾讯开源的GT

    GT是一款同时支持安卓手机端和IOS手机端性能测试工具。

    GT(随身调),即仅凭一部手机,无需连接电脑,就可以对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等)、 开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等等;更重要的是,您可以在任意真实场所、 任何时候做如上的系列事情,这就是“随身调”。

    如果您觉得GT提供的功能还不够满足您的需要, 您还可以利用GT提供的基础API自行开发有特殊功能的GT插件(仅iOS版支持), 帮助您解决更加复杂的APP调试、测试问题。

使用步骤:

GT支持iOS和Android两个手机平台,其中: Android版由一个可直接安装的GT控制台APP 和GT SDK插件扩展检测。GT控制台可以独立安装使用,SDK需嵌入被调测的应用、并利用GT控制台进行信息展示和参数修改。 iOS版是一个Framework包,必须嵌入APP工程,编译出带GT的APP才能使用;iPhone和iPad应用都能支持。

以下为Android版GT控制台APP 检测基础功能案例,使用步骤:

1、应用宝下载GT.APP,安装运行GT。

2、选择应用  

3、选择关注的监控数据   

(三)科大讯飞的iTest  http://www.liqucn.com/rj/410791.shtml

iTest官方说该工具由科大讯飞测试技术部开发,在多个项目中成功应用,具有较高的准确性和稳定性。它填补了手机端自动化测试的空白,以实用高效为宗旨,记录特定应用的性能消耗情况,包括cpu、内存、流量、电量等信息。我们知道科大讯飞在业界是很有名气的是讯飞语音。但是关于这款检测工具,遗憾本人寻遍全网,只能查找下载安装Apk的地址,查阅其他的相关介绍和资料太少。

(四)Google的开源Battery Historian

(五)Android 自带 Lint 工具

   Android Lint Tool 是 Android Sutido 集成的一个代码规范提示工具,使用 Lint 检测代码、布局文件、去除多余资源。
硬编码会提示以级别警告,例如:在布局文件中写了三层冗余的LinearLayout布局、直接在TextView中写要显示的文字、字体大小使用dp而不是sp为单位,就会在编辑器右边看到提示。
使用Android Studio的lint可以清除无用的资源文件(点击菜单栏的Analyze -> Run Inspection by Name, 输入unused resource)。
    当然两个都是一个简单的举例,Lint的功能非常强大,大家应该养成写完代码查看Lint的习惯,这不仅让你及时发现代码种隐藏的一些问题,更能让你养成良好的代码风格,要知道,这些Lint提示可都是Google大牛们汗水合智慧的结晶。

二、性能优化

根据用户的四个方面需求,总结如下:

  1. 追求流畅,防止卡顿
  2. 追求稳定,防止闪退
  3. 追求续航,防止耗损
  4. 追求精简,防止臃肿

(最重要是稳定,app出现闪退崩溃是致命的。相比之下卡顿耗损安装包大都还好些。)

(一)追求稳定,防止闪退
        一般造成Crash和ANR的都会出现应用崩溃的表现。造成ANR程序无响应的原因主要是在四大组件的耗时操作;而造成Crash的原因却有很多,比如运行时异常的空指针、数组越界、未实例化、强制类型、低内存机制等等,有些时候我们在开发测试阶段都没有出现异常崩溃现象,而发布上线后到了用户手机就会出现各种奇怪闪退。

        虽然我们无法保证开发完美至极不出现异常,但是可以努力做好异常的捕获。通常我们会使用 try - catch,在发现容易出现崩溃的代码块,主动加上try-catch 预防异常闪退。但是没加try-catch的代码块出现异常还是闪退该怎么办?我们可以通过设置 UncaughtExceptionHandler 捕获全局线程异常,而在主线程抛出异常时,APP依旧会闪退进程重启。那么可以使用 Cockroach (蟑螂),可以保证不管怎样抛异常都不会闪退,App进程也不会重启。
        以上治标不治本,需要不断加强代码的严谨性去减少Crash率。由于Android应用的沙箱机制,每个应用程序都运行在一个进程中,拥有一个独立的Dalvik虚拟机实例,系统默认分配给虚拟机的内存是有限度的。当系统内存太低依然会触发LMK(Low Memory Killer)机制,即闪退、崩溃现象。不同厂商不同,如:华为mate7,192m ;小米4,128m ;红米,128m 。而在,Android4.0以后,可以通过在application节点中设置属性android:largeHeap=”true”来设置最大可分配多少内存空间就可以突破一定限制。

内存分析工具

(1)Memory Monitor 工具:

      它是Android Studio自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。通过点击Android Studio右下角的Memory Monitor标签,打开工具可以看见较浅蓝色代表free的内存,而深色的部分代表使用的内存从内存变换的走势图变换,可以判断关于内存的使用状态,例如当内存持续增高时,可能发生内存泄漏;当内存突然减少时,可能发生GC等

(2)Memory Analyzer 工具:

       MAT(Memory Analyzer Tool) 是一个快速,功能丰富的 Java Heap 分析工具,通过分析 Java 进程的内存快照 HPROF 分析,从众多的对象中分析,快速计算出在内存中对象占用的大小,查看哪些对象不能被垃圾收集器回收,并可以通过视图直观地查看可能造成这种结果的对象。

(3)LeakCanary工具:

      LeakCanary 只在debug版本下检测,正版先上线后自动跳过检测这就方便开发者无需操作每次上线时注释检测代码。这个工具是Square公司在Github开源的。
如何使用?GitHup官网https://github.com/square/leakcanary,首先在Gradle文件里添加依赖。
在Application中写方法:

    private RefWatcher setupLeakCanary() {
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return RefWatcher.DISABLED;
        }
        return LeakCanary.install(this);
    }
 
    public static RefWatcher getRefWatcher(Context context) {
        MyApplication leakApplication = (MyApplication) context.getApplicationContext();
        return leakApplication.refWatcher;
    }
然后onCreate()中调用即可:refWatcher = setupLeakCanary();

在Activity中单独调用检测:

@Override
    protected void onDestroy() {
        super.onDestroy();
        RefWatcher refWatcher = MyApplication.getRefWatcher(this);//1
        refWatcher.watch(this);
    }

(二)追求流畅,防止卡顿

卡顿的场景通常是发生在用户交互体验最直接的方面。大概分为四个方面,如下图所示。

影响卡顿的两大因素,分别是界面绘制和数据处理。
界面绘制:主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在 UI 和启动后的初始界面以及跳转到页面的绘制上。
数据处理:导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理 UI 线程,二是数据处理占用 CPU 高,导致主线程拿不到时间片,三是内存增加导致 GC 频繁,从而引起卡顿。

(1)布局优化
    在Android种系统对View进行测量、布局和绘制时,都是通过对View数的遍历来进行操作的。如果一个View数的高度太高就会严重影响测量、布局和绘制的速度。Google也在其API文档中建议View高度不宜哦过10层。现在版本种Google使用RelativeLayout替代LineraLayout作为默认根布局,目的就是降低LineraLayout嵌套产生布局树的高度,从而提高UI渲染的效率。
布局复用,使用标签重用layout;
提高显示速度,使用延迟View加载;
减少层级,使用标签替换父级布局;
注意使用wrap_content,会增加measure计算成本;

删除控件中无用属性;

(2)绘制优化
    过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。如何避免过度绘制?
布局上的优化。移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片

自定义View优化。使用 canvas.clipRect() 帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。


(3)启动优化
   启动优化工具。 应用一般都有闪屏页SplashActivity,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。
    (另外,还可以IDE自带的一款UI绘制检测图形化数据分析工具 Systrace ,4.0版本以上版本可以使用。这里暂不介绍)

    启动白屏或黑屏问题优化处理。当我们在启动一个应用时,系统会去检查是否已经存在这样一个进程,如果不存在,系统的服务会先检查startActivity中的intent的信息,然后在去创建进程,最后启动Acitivy,即冷启动。而启动出现白黑屏的问题,就是在这段时间内产生的。系统在绘制页面加载布局之前,首先会初始化窗口(Window),而在进行这一步操作时,系统会根据我们设置的Theme来指定它的Theme 主题颜色,我们在Style中的设置就决定了显示的是白屏还是黑屏。详情查看请点击

    启动加载逻辑优化处理。闪屏页的存在可以说就是启动优化,通常在闪屏页延迟2秒跳转到主界面,但是在进入首页的时候,首页复杂的View渲染以及必须在UI线程执行的业务逻辑,必然拖慢了启动速度。启动闪屏页虽然简单执行快,首页却复杂执行慢,应用启动前轻后重。可以采用分布加载、异步加载、延期加载策略来提高应用启动速。例如,把SplashActivity改成SplashFragment,应用程序的入口变成MainActivity,在MainActivity中先展示SplashFragment,显示完毕后再移除SplashFragment。这样,在SplashFragment的2S的友好时间内进行数据准备的同时,首页的View就能够被加载,首页的业务逻辑就能够被执行。在闪屏页窗口加载完毕后,我们加载activity_main的布局,考虑到这个布局有可能比较复杂,耽误View的解析时间,可以采用ViewStub的形式进行懒加载。
(4)刷新优化
减少刷新次数,灵活利用缓存及限时刷新;
缩小刷新区域,局部刷新,避免多余请求;
(5)动画优化
      需要实现动画效果时,需要根据不同场景选择合适的动画框架来实现。
      有些情况下,可以用硬件加速方式来提供流畅度降低动画卡顿。

(三)节省——耗电优化

 在移动设备中,电池的重要性自然不言而喻,如果手机没电了应用功能技术实现再怎么牛逼,用户也什么都干不成。对于Android操作系统和设备各大开发商来说,对手机耗电的优化从没有停止过,不断地追求更长的待机时间。而对于开发一款应用来说,绝不可以忽略电量耗损的问题,被归为“电池杀手”的应用,最终的结果无疑是走向被用户卸载的道路。比如,有些应用为了保持应用进程长期在后台存活,使用各种不合理进程保活方案,破坏操作系统“生态平衡”,导致用户电量严重耗损,虽然这种流氓开发行为并不违法吧,但是也属于不道德的行为,也同样会被同行所被鄙视的行为。

    在 Android5.0 以前,关于应用电量消耗的测试即麻烦又不准确,而5.0 之后Google专门引入了一个获取设备上电量消耗信息的API—— Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系统电量分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况。

    最后提供一些可供参考耗电优化的方法:

(1)计算优化。算法、for循环优化、Switch..case替代if..else、避开浮点运算。
        浮点运算:计算机里整数和小数形式就是按普通格式进行存储,例如1024、3.1415926等等,这个没什么特点,但是这样的数精度不高,表达也不够全面,为了能够有一种数的通用表示法,就发明了浮点数。浮点数的表示形式有点像科学计数法(*.*****×10^***),它的表示形式是0.*****×10^***,在计算机中的形式为 .***** e ±***),其中前面的星号代表定点小数,也就是整数部分为0的纯小数,后面的指数部分是定点整数。利用这样的形式就能表示出任意一个整数和小数,例如1024就能表示成0.1024×10^4,也就是 .1024e+004,3.1415926就能表示成0.31415926×10^1,也就是 .31415926e+001,这就是浮点数。浮点数进行的运算就是浮点运算。浮点运算比常规运算更复杂,因此计算机进行浮点运算速度要比进行常规运算慢得多。

(2)避免 Wake Lock 使用不当。
    Wake Lock是一种锁的机制,主要是相对系统的休眠而言的,,只要有人拿着这个锁,系统就无法进入休眠意思就是我的程序给CPU加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。有的情况如果不这么做就会出现一些问题,比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。所以微信里面是有大量使用到了Wake_Lock锁。系统为了节省电量,CPU在没有任务忙的时候就会自动进入休眠。有任务需要唤醒CPU高效执行的时候,就会给CPU加Wake_Lock锁。大家经常犯的错误,我们很容易去唤醒CPU来工作,但是很容易忘记释放Wake_Lock。

(3)使用 Job Scheduler 管理后台任务。
   在Android 5.0 API 21 中,google提供了一个叫做JobScheduler API的组件,来处理当某个时间点或者当满足某个特定的条件时执行一个任务的场景,例如当用户在夜间休息时或设备接通电源适配器连接WiFi启动下载更新的任务。这样可以在减少资源消耗的同时提升应用的效率。

(四)安装包——APK瘦身

 

assets文件夹。存放一些配置文件、资源文件,assets不会自动生成对应的 ID,而是通过 AssetManager 类的接口获取。

res。res 是 resource 的缩写,这个目录存放资源文件,会自动生成对应的 ID 并映射到 .R 文件中,访问直接使用资源 ID。

META-INF。保存应用的签名信息,签名信息可以验证 APK 文件的完整性。

AndroidManifest.xml。这个文件用来描述 Android 应用的配置信息,一些组件的注册信息、可使用权限等。

classes.dex。Dalvik 字节码程序,让 Dalvik 虚拟机可执行,一般情况下,Android 应用在打包时通过 Android SDK 中的 dx 工具将 Java 字节码转换为 Dalvik 字节码。

resources.arsc。记录着资源文件和资源 ID 之间的映射关系,用来根据资源 ID 寻找资源。

(2)减少安装包大小
1.代码混淆。使用IDE 自带的 proGuard 代码混淆器工具 ,它包括压缩、优化、混淆等功能。

2.资源优化。比如使用 Android Lint 删除冗余资源,资源文件最少化等。(这个前面已经讲过了

3.图片优化。比如利用 PNG优化工具 对图片做压缩处理。如果应用在4.0版本以上,推荐使用 WebP图片格

4.可以使用微信开源资源文件混淆工具——AndResGuard 。一般可以压缩apk的1M左右大。

5.插件化热修复开发。比如功能模块放在服务器上,按需下载,可以减少安装包大小。

6.避免重复或无用功能的第三方库。例如,百度地图接入基础地图即可、讯飞语音无需接入离线、图片库Glide\Picasso等

 

 

 

你可能感兴趣的:(Android,Java)