首页 > 代码库 > Android开发学习之路--性能优化之常用工具

Android开发学习之路--性能优化之常用工具

??android性能优化相关的开发工具有很多很多种,这里对如下六个工具做个简单的使用介绍,主要有Android开发者选项,分析具体耗时的Trace view,布局复杂度工具Hierarchy View,应用启动时间,Memory、CPU、Network分析,静态代码检查工具Lint以及程序稳定性monkey。下面就开始学习下这些工具吧。

一、Android开发者选项

??Andorid开发工具众多,首先就是手机自带的开发者选项了,至于手机怎么启动开发者选项,那么请自行百度或者google了,接着简单熟悉下各个选项:

技术分享
??1、Take bug report(进行漏洞报告): 点击这个选项会获取当前设备的log信息文件,打包并准备发送我们想要发送的人。这会花费1、2分钟,然后会看到一个准备好的提示信息,然后可以点击发送。 ??2、Desktop backup password(桌面备份密码):可以使用adb备份和存储app和他们的关联数据到你的电脑。这个选项强制需要一个密码备份和存储。 ??3、Stay awake(保持唤醒):选中这个复选框会强制屏幕唤醒,只要连接上usb线或者充电的时候都会不进入休眠,当需要调试的时候不用老是去解锁了,相当方便。 ??4、Select runtime(选择运行时):你可以选择Dalvik或者ART。ART仍然是实验性的,直到Android L才最终release。 ??5、Enable Bluetooth HCI snoop log(蓝牙HCI搜索日志):有时,开发者需要获取和分析蓝牙的HCI包,使能这个会在设备storage(路径为:/sdcard/btsnoop_hco.log)中保存包的信息。接着你可以使用类似wireshark等软件分析。 ??6、Process stats(程序状态):你需要知道的所有运行在手机上的程序的任何信息。包括了ram使用量,运行时间等。 ??7、USB debugging(USB调试):USB调试时使用,使用DDMS和ADB命令的时候也需要这个使能,不勾选这个就不能调试我们的应用了。 ??8、Revoke USB debugging authorizations(撤回USB除错授权):当第一次USB线连接电脑的时候,需要认证并且建立密钥,这个操作删除这个认证,强制重新来一遍。 ??9、Power menu bug reports(电源菜单中包括漏洞报告):在电源菜单中包括用于进行漏洞报告的选项。 ??10、Allow mock locations(允许虚拟位置):允许手动写入位置信息,对于需要模拟位置的应用来说十分方便,可以干一些坏事,你懂得。 ??11、Select debug app(选择待调试的应用程序):这个设置让你选择一个待调试的应用。 ??12、Wait for debugger(等待调试程序):等待调试程序 ??13、Show touches(显示触摸位置):显示触摸的位置,一般是一个小圈圈。 ??14、Pointer location(显示指针位置):显示出当前位置的坐标。
技术分享
??15、Show surface updates(显示屏幕更新):屏幕更新时会闪烁。 ??16、Show layout bounds(显示布局边界):显示剪切边界、边缘。
技术分享
??17、Force RTL layout direction(强制RTL布局):界面布局从右至左。 ??18、Window animation scale(窗口动画比例):窗口动画的比例,数字越小,速度越快。 ??19、Transition animation scale(过渡动画比例):过渡动画的比例,同上。 ??20、Simulate secondary displays(模拟二级显示):允许开发者模拟不同尺寸的表现。 ??21、Force GPU rendering(强制GPU渲染):强制应用使用硬件2D渲染除非应用本身不需要。 ??22、Show GPU view updates(显示GPU视图更新):任何用硬件GPU来绘制视图的会有红色的覆盖层。 ??23、Show hardware layer updates(显示硬件层更新):这个设置会告诉你什么时候硬件层在更新。 ??24、Debug GPU overdraw(调试GPU过度渲染):过度渲染发生在任何时候当应用请求系统绘制一些视图在其他视图之上的时候。
技术分享
??25、Force 4x MSAA(启动4x MSAA):这个设置强制多重采样抗锯齿。MSAA就是寻找出物体边缘部分的像素,然后再把画缩放到当前的显示器上。会降低性能提升视觉的美感。 ??26、Strict mode enabled(严格模式):应用程序在主线程上执行长时间操作屏幕会闪烁。 ??27、Show CPU usage(显示CPU使用情况):在屏幕右上角显示当前CPU的信息。
技术分享
??28、Profile GPU rendering(GPU显示配置文件):这个设置可以在屏幕上显示也可以写入到文件中。
技术分享
??29、Enable OpenGL traces(启动OpenGL跟踪):这个设置是观察OpenGL的错误,并把log保存到文件中。 ??30、Don’t keep activities(不保留活动):用户离开后立即清理每个活动。 ??31、Background process limit(限制后台进程):允许当前后台运行多少个进程的一个选择。 ??32、Show all ANRs(显示全部ANR):当应用有bug的时候回显示应用无响应对话框。

二、应用具体耗时工具Trace view

??Trace view用于查找程序运行时具体耗时在哪,它显示两个面板,一个是Timeline面板,描述每一个线程和方法启动和结束的时间。另一个是Profile面板,提供一个所有方法内部发生了什么的概要。
??先新建工程PerformanceTool,然后新建布局main_activity_layout.xml,一个按钮用来加载一个网页;另一个页面就是一个webview。

技术分享
??然后编写代码,首先是MainActivity.java:
package com.jared.performancetool;

import android.databinding.DataBindingUtil;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.jared.performancetool.databinding.MainBinding;

public class MainActivity extends AppCompatActivity {

    MainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        initView();
    }

    private void initView() {
        binding.btnLoad.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                WebViewActivity.launch(MainActivity.this);
            }
        });
    }
}

??接着是WebviewActivity.java:

package com.jared.performancetool;

import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import com.jared.performancetool.databinding.WebViewBinding;

/**
 * Created by jared on 2017/1/10.
 */

public class WebViewActivity extends AppCompatActivity {

    WebViewBinding binding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_webview_layout);
        initView();
    }

    private void initView() {
        binding.webView.loadUrl("http://www.hoolay.cn/ihoolay");
    }

    public static void launch(Context context) {
        Intent intent = new Intent(context, WebViewActivity.class);
        context.startActivity(intent);
    }
}

1、view形式

??traceview有两种使用方法,一种是直接通过DDMS工具来start和stop trace,使用方法如下:
??接着运行程序,成功运行后,点击菜单栏的Tools -> Android -> Android Device Monitor :

技术分享
??进入Monitor之后,点击DDMS:
技术分享
??这个时候在monitor的左边面板会出现
技术分享
??点击对应要trace的包名,然后点击Stop左边的有个小红点的按钮。
技术分享
??点击ok之后便开始执行trace了,这个时候再点击那个app里面的加载网页的按钮,加载完后,再次点击那个STOP左边那个变成小黑点的按钮。 ??接着便trace完成了,就可以查看如下两个面板了。
技术分享
??上图就是Timeline面板,左边就是每行都是显示一个线程,右边对应它的时间线。可以看出来主要就是main线程在做事情。
技术分享
??上图就是Profile面板,首先是左边的name,比如序号为86,这里展开有Parents和Children,其中Parents就是调用该方法的方法,这里initView在onCreate中被调用,Children就是该方法内部调用的方法,这里调用了loadUrl。与项目中的真实的代码完全相符。 ??接着看下右边一排的Incl Cpu Time、Excl Cpu Time、Incl Real Time、Excl Real Time、Call+Recur Calls/Total、Cpu Time/Call、Real Time/Call。 ??Incl Cpu Time:某方法占用CPU的时间,包含内部调用其他方法占用CPU的时间。 ??Excl Cpu Time:某方法占用CPU的时间,不包含内部调用其他方法所占用的CPU时间。 ??Incl Real Time:某方法运行的真实的时间(单位ms),包含内部调用其他方法所占用的真实时间。 ??Excl Real Time:某方法运行的真实的时间(单位ms),不包含内部调用其他方法所占用的真实时间。 ??Call+Recur Calls/Total:某方法被调用的次数以及递归调用占总调用次数的百分比。 ??Cpu Time/Call:某方法占用CPU的时间和次数的比例。 ??Cpu Time/Call:某方法占用CPI真实时间和调用次数的比例。

2、代码形式

??另一种是通过注入代码来实现:
??在WebviewActivity的onCreate代码中加入两行代码如下:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this, R.layout.activity_webview_layout);
    Debug.startMethodTracing("perform");
    initView();
    Debug.stopMethodTracing();
}

??别忘了加上SD卡的读写权限,然后运行app,点击加载网页按钮,就会在/sdcard目录下生产perform.trace文件,通过adb pull可以把文件导出来。

?  ~ adb pull /sdcard/perform.trace Downloads/

??这里导出到了Downloads目录下,然后通过AndroidMonitor的file->open file选择这个文件打开:

技术分享
??然后就可以查看分析了。通过代码的好处就是比较精确的得到我们想要测试的,不过代价就是要写代码编译,导出来,步骤相对来说比较繁琐。而直接使用工具的话只是一个大概的范围,但是方便快捷。可以视情况使用其中之一。

三、布局复杂度工具Hierarchy View

??之前文章《Android性能优化之布局》已经讲过了Hierarchy View的简单使用。这里还是继续讲解下怎么使用。Hierarchy View主要是检测布局复杂度,各视图的布局耗时情况的一个工具,它需要在模拟器上进行,真机好像也有方法解决,不过很懒没去折腾,主要还是学习工具为主嘛。
??点击菜单Tools -> Android -> Android Device Monitor:

技术分享
??然后进入到Android Device Monitor,选中Hierarchy View
技术分享
??选中后会出现层级树。
技术分享
??然后我们点击那个加载网页的button,可以看到对应的加载耗时,分别有Measure,Layout和Draw的耗时。 ??我们可以根据其耗时来优化我们界面。

四、应用启动时间

??一般我们都会比较关注一个app启动的时间,如果启动太慢了,用户可能就不想玩了,这里有个方法可以测试应用启动的时间:
??命令行如下:

adb shell am start -W packagename/activity

??这里举个例子,比如说是上述项目中的PerformaceTool app,那么首先打开终端,连接上usb线,然后终端输入:

?  ~ adb shell am start -W com.jared.performancetool/.MainActivity

??等待会儿,app会启动,并且输出如下所示信息:

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.jared.performancetool/.MainActivity }
Status: ok
Activity: com.jared.performancetool/.MainActivity
ThisTime: 158
TotalTime: 158
WaitTime: 172
Complete

??如上所示可以看出用时158ms。

五、Memory、CPU、Network

??很多时候我们需要了解app的内存使用情况,CPU占用怎样,网络速度如何。为了提高性能,我们总是想把内存减少到最小,CPU占用率近可能小,网络情况适宜。当然这些可以用命令行实现,毕竟androd基于linux操作系统的,但是那样显得很麻烦又不是很直观,很庆幸Android Studio自带了功能。
??Android Studio的Android Monitor里面有logcat和Monitors,选中monitors就有对于Memory,CPU和Network的展示。如下图所示:

技术分享
??这里展示了Memory的使用量,CPU的占用量,以及网络的速度。上图就是点击了加载网页时候的一个分布情况。它可以帮我们查看并优化我们的程序,从而显得非常的直观。

六、 静态代码检查工具Lint

??Lint主要是提供一套静态代码分析的工具,它可以帮助我们检查项目中存在的问题,让我们更有规范性的开发App。运行菜单的analyze->Inspect Code。

技术分享
??稍息片刻系统就会分析完成,如下所示:
技术分享
??Lint分很多子项。Internationalization国际化问题,硬编码的文字都是需要添加进@string资源,Security安全性问题,Usability可用性问题,未使用到资源、资源缺少的问题等等,具体可以根据分析后的结果来一步步改善。

七、程序稳定性:monkey

??通过monkey对程序在提交测试前做自测,可以检测出明显的导致程序不稳定的问题,执行monkey只需要一行命令,提交测试前跑一次可以避免应用刚提交就被打回的问题。

?  ~ adb shell monkey -p com.jared.performancetool -v 500

??-p表示包名,-v表示反馈级别 500就是500个伪随机事件
??若在压力测试中程序崩溃或者接收到任何失控异常,就会自动停止。

参考:
https://developer.android.com/studio/profile/traceview.html#traceviewLayout
http://www.jianshu.com/p/07b551ee260b

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    Android开发学习之路--性能优化之常用工具