traceview android studio,TraceView 的正确打开方式

traceview android studio,TraceView 的正确打开方式引言 TraceView 是 AndroidSDK 提供的一个性能分析工具官网介绍 一般用来检查 UI 卡顿 分析 app 耗时操作 但是对于大多说 Android 开发来说 TraceView 的图形化页面只能让人感觉一脸懵逼 本文重点昨天在干货集中营发现这一篇文章一个能让你了解所有函数调用顺序以及函数耗时的 Android 库 无需侵入式代码 文里面提到可以使用 dmtracedump

引言

TraceView 是 Android SDK 提供的一个性能分析工具官网介绍 ,一般用来检查 UI 卡顿、分析 app 耗时操作。但是对于大多说 Android 开发来说,TraceView 的图形化页面只能让人感觉一脸懵逼!!!

本文重点

昨天在干货集中营 发现这一篇文章 一个能让你了解所有函数调用顺序以及函数耗时的Android库(无需侵入式代码) 文里面提到可以使用 dmtracedump 命令把 trace 文件转为 txt ,然后再从 txt 里面提取我们需要的信息。

以上为本文全部主要内容,下面的啰嗦都是对以上内容的具体阐释。

获得 trace 文件

通过点击 DDMS start Method Profiling (第一次点击开始,第二次点击结束)

1e038ef2e586

traceview_picture_1.png

1e038ef2e586

traceview_picture_2.png

在代码中通过使用

android.os.Debug.startMethodTracing()

android.os.Debug.stopMethodTracing()

生成 traceView ,然后通过下面的 adb pull 命令导出 traceView

在 AndroidStudio 中获取,这个是本文重点,上面两种方式纯属为了凑数

点击 monitors cpu 模块的小闹钟(第一次点击开始,第二次点击结束)

1e038ef2e586

traceview_picture_3.png

然后 trace 文件会被存放在项目根目录的 captures 目录。

在项目根目录的 gradle 文件中增加一个 task

task AppOutPutMethodOrder() {

doLast {

def capturesDirPath = project.getProjectDir().path + File.separator + “captures”;

def capturesDir = new File(capturesDirPath);

capturesDir.traverse {

if (it.isFile() && it.name.endsWith(“.trace”)) {

def orderName = it.name.replace(“trace”, “txt”)

def orderFile = new File(capturesDirPath, orderName)

orderFile.write(“”)

def dmtracedumpDir = getDmtraceDumpDir();

//说明:dmtracedump 为 android sdk自带工具,要执行dmtracedump命令则需要先添加环境变量

def baseComand = dmtracedumpDir + “dmtracedump -ho ” + it.absolutePath + ” >> ” + orderFile.absolutePath

println baseComand

String osNameMatch = System.getProperty(“os.name”).toLowerCase();

if (osNameMatch.contains(“windows”)) {

(“cmd /c start /b ” + baseComand).execute()

} else {

[“bash”, “-c”, baseComand].execute()

}

}

}

}

}

执行命令

gradlew AppOutPutMethodOrder

利用 dmtracedump 命令把 trace 文件转为 txt 文件

1e038ef2e586

traceview_picture_4.png

txt 文件比较大,AndroidStudio 自带的文本阅读器打不开,需要用其他工具打开(这里使用的是 sublime Text)下面是截取的一部分 txt 内容

1e038ef2e586

traceview_picture_5.png

这个文件有下面几个重要信息

1. VERSION ~ Trace (1~29行)是线程信息,前面是线程 id 后面是 线程名称。

2. Trace 以后是方法信息。

第一部分是线程 id

第二部分 ent 代码方法开始执行,xit 表示方法执行完毕

第三部分表示当时的时间戳,单位是微秒(μs)

第四部分表示方法名,参数类名

提取需要的信息

在 gradle 再增加一个 task

task AppFilterMethodOrder() {

doLast {

//TODO 替换为你想要过滤的包名

def filterPackageName = “com.xxx.xxx”

if (project.hasProperty(“package_name”)) {

filterPackageName = project.getProperty(“package_name”)

}

//处理包名

def filterSignature = filterPackageName.replaceAll(“[.]”, “/”)

def capturesDirPath = project.getProjectDir().path + File.separator + “captures”;

def capturesDir = new File(capturesDirPath);

capturesDir.traverse {

if (it.isFile() && it.name.endsWith(“.txt”) && !it.name.contains(“–filter”)) {

def orderName = it.name.replace(“.txt”, “–filter.txt”)

def orderFile = new File(capturesDirPath, orderName)

orderFile.write(“”)

def map = new HashMap();

it.eachLine { line ->

if (line.contains(filterPackageName) || line.contains(filterSignature)) {

if (line.contains(“ent”)) {

line = line.replaceAll(“[.]{2,}+”, “”)

line = line.replaceAll(“[ ]{2,}+”, ” “)

def item = line.split(” “);

map.put(item[3], item[2])

} else if (line.contains(“xit”)) {

line = line.replaceAll(“[.]{2,}+”, “”)

line = line.replaceAll(“[ ]{2,}+”, ” “)

def item = line.split(” “);

// for (int i = 0; i < item.length; i++) {

// println “–” + i + “:” + item[i]

// }

println map.size()

// println map.containsKey(item[3])

if (map.containsKey(item[3])) {

println item[3] + ” 耗时:” + (item[2].toInteger() – map.get(item[3]).toInteger())/1000 + ” 毫秒”

orderFile.append(“耗时:\t\t” + (item[2].toInteger() – map.get(item[3]).toInteger())/1000 + ” 毫秒” + “\t\t” + item[3])

orderFile.append(“\n”)

map.remove(item[3])

}

}

}

}

}

}

}

}

执行代码

gradlew AppFilterMethodOrder -P package_name=com.xxx.xxx

这个 task 中,我们根据包名提取需要的信息得到

1e038ef2e586

traceview_picture_6.png

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216345.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午12:03
下一篇 2026年3月18日 下午12:03


相关推荐

  • 工作流(Workflow)与智能体(Agent)的区别

    工作流(Workflow)与智能体(Agent)的区别

    2026年3月16日
    2
  • HikariPool-1 – Connection is not available, request timed out after 30000ms.

    HikariPool-1 – Connection is not available, request timed out after 30000ms.HikariPool是号称史上最快的数据库连接池,而且目前来看确实是这样的,SpringBoot2.0也已经采用HikariCP作为默认连接池配置.近期项目也将druid切成了HikariPool,但HikariPool仍然不够稳定,经常出现获取不到数据库连接,连接数不够的问题尝试修改HikariPool连接池配置,增大最大连接数,MaximumPoolSize由30改为100…

    2022年6月23日
    32
  • mybatis循环map的一些技巧

    mybatis循环map的一些技巧原文:http://blog.csdn.net/linminqin/article/details/39154133——————————————-循环key:[java] viewplain copy”condition.keys” item=”k” separator

    2022年10月21日
    5
  • 软件著作权登记申请时的60页源代码格式

    软件著作权登记申请时的60页源代码格式申请软件著作权登记的时候会被要求提交 60 页的源代码 没有经验的开发者朋友第一次申请的时候难免会遇到因代码文档格式不正确 代码里含有其他版权信息等原因被要求补正的问题 从而导致拿证时间延误 为了帮助开发者朋友一次性顺利通过软件著作权登记的审查 下面为大家分享下自己总结的 60 页源代码整理攻略 第一步 请点击下载软件著作权登记源代码模板 第二步 将打算申请软著的软件名称及版本号替换模板里左上角 自助登记安卓版应用软件 V1 0 第三步 打开软件的代码文件 复制代码 第四步 回到本文档 Ctal A

    2026年3月17日
    2
  • es6中padStart和padEnd

    es6中padStart和padEndpadStart和padEnd是es6中新增的语法这两个方法都是字符串原型上的方法,所以只能对字符串使用是新增的方法不会修改原字符串,只有es5才会改变原数据str.padStart(MaxLength,’填充的内容’)//当str的长度没有达到MaxLength,会将第二个参数填充到这个str前直到相当str.padEnd(MaxLength,’填充的内容’)//和上面一样不过是…

    2025年9月16日
    6
  • Java面试知识点汇总

    Java面试知识点汇总为了找到心仪的工作而努力吧最近在刷各种面经 把学会的知识点汇总一下以便查漏补缺 未完待续

    2026年3月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号