自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一個能讓你了解所有函數(shù)調(diào)用順序的Android庫

移動開發(fā) Android
這個項目可以讓你以包名為過濾點過濾你想要知道所有函數(shù)調(diào)用順序。

[[187210]]

背景

當項目代碼量很大的時候,或者你作為一名新人要快速掌握代碼的時候,給函數(shù)打上log,來了解代碼執(zhí)行邏輯,這種方式會顯然成本太大,要改動項目編譯運行,NO!太耗時;或者你想debug的方式來給你想關(guān)注的幾個函數(shù),來了解代碼執(zhí)行邏輯,NO!因為你肯定會漏掉函數(shù);也許你可以固執(zhí)的給你寫的項目打滿log說這樣也行,但是你要知道你方法所調(diào)用的jdk的函數(shù)或者第三方aar或者jar再或者android sdk中的函數(shù)調(diào)用順序你怎么辦,還能打log嗎?顯然不行吧,來~這個項目給讓可以讓你以包名為過濾點過濾你想要知道所有函數(shù)調(diào)用順序。

效果奉上

 

 

 

 

動作簡介:首先點擊MainActivity的自定義MyTextView然后進入SecondActivity再點擊textview之后finish跳轉(zhuǎn)回MainActivity

下面是庫處理過所得到的函數(shù)調(diào)用順序order.txt文件(我這里屏蔽了jdk函數(shù),第三方庫函數(shù),以及android sdk中函數(shù),換句話說我就保留了我自己包名中的函數(shù)順序)

832 ent     67593 .....com.zjw.appmethodorder.MainActivity.onClick (Landroid/view/View;)VMainActivity.java
832 ent     99956 ..........com.zjw.appmethodorder.MainActivity.onPause ()VMainActivity.java
832 ent     99970 ...........com.zjw.appmethodorder.BaseActivity.onPause ()VBaseActivity.java
832 ent    100472 ............com.zjw.appmethodorder.BaseActivity.baseOnPause ()VBaseActivity.java
832 ent    128540 ........com.zjw.appmethodorder.SecondActivity. ()VSecondActivity.java 832 ent    128562 .........com.zjw.appmethodorder.BaseActivity. ()VBaseActivity.java 832 ent    213911 ........com.zjw.appmethodorder.SecondActivity.onCreate (Landroid/os/Bundle;)VSecondActivity.java 832 ent    213928 .........com.zjw.appmethodorder.BaseActivity.onCreate (Landroid/os/Bundle;)VBaseActivity.java 832 ent    258414 ..........com.zjw.appmethodorder.BaseActivity.baseOnCreate ()VBaseActivity.java 832 ent   1440503 .........com.zjw.appmethodorder.SecondActivity.onResume ()VSecondActivity.java 832 ent   1440563 ..........com.zjw.appmethodorder.BaseActivity.onResume ()VBaseActivity.java 832 ent   1445675 ...........com.zjw.appmethodorder.BaseActivity.baseOnResume ()VBaseActivity.java 832 ent   2954291 .................com.zjw.appmethodorder.MyTextView.onWindowVisibilityChanged (I)VMyTextView.java 832 ent   3065664 ........com.zjw.appmethodorder.MainActivity.onStop ()VMainActivity.java 832 ent   3065701 .........com.zjw.appmethodorder.BaseActivity.onStop ()VBaseActivity.java 832 ent   3069155 ..........com.zjw.appmethodorder.BaseActivity.baseOnStop ()VBaseActivity.java 832 ent   3139519 .......com.zjw.appmethodorder.SecondActivity.click (Landroid/view/View;)VSecondActivity.java 832 ent   3146300 ........com.zjw.appmethodorder.SecondActivity.finish ()VSecondActivity.java 832 ent   3183478 ..........com.zjw.appmethodorder.SecondActivity.onPause ()VSecondActivity.java 832 ent   3183498 ...........com.zjw.appmethodorder.BaseActivity.onPause ()VBaseActivity.java 832 ent   3183843 ............com.zjw.appmethodorder.BaseActivity.baseOnPause ()VBaseActivity.java 832 ent   3209420 ........com.zjw.appmethodorder.MainActivity. ()VMainActivity.java 832 ent   3209438 .........com.zjw.appmethodorder.BaseActivity. ()VBaseActivity.java 832 ent   3283359 ........com.zjw.appmethodorder.MainActivity.onCreate (Landroid/os/Bundle;)VMainActivity.java 832 ent   3283378 .........com.zjw.appmethodorder.BaseActivity.onCreate (Landroid/os/Bundle;)VBaseActivity.java 832 ent   3330938 ..........com.zjw.appmethodorder.BaseActivity.baseOnCreate ()VBaseActivity.java 832 ent   4363295 .....................com.zjw.appmethodorder.MyTextView. (Landroid/content/Context;Landroid/util/AttributeSet;)VMyTextView.java 832 ent   4436094 ..................com.zjw.appmethodorder.MyTextView.onFinishInflate ()VMyTextView.java 832 ent   4449689 .........com.zjw.appmethodorder.MainActivity.initView ()VMainActivity.java 832 ent   4539427 .........com.zjw.appmethodorder.MainActivity.onResume ()VMainActivity.java 832 ent   4539467 ..........com.zjw.appmethodorder.BaseActivity.onResume ()VBaseActivity.java 832 ent   4543597 ...........com.zjw.appmethodorder.BaseActivity.baseOnResume ()VBaseActivity.java 832 ent   4917854 .................com.zjw.appmethodorder.MyTextView.onAttachedToWindow ()VMyTextView.java 832 ent   4918658 .................com.zjw.appmethodorder.MyTextView.onWindowVisibilityChanged (I)VMyTextView.java 832 ent   5090653 ...................................com.zjw.appmethodorder.MyTextView.onMeasure (II)VMyTextView.java 832 ent   5355203 ..................................com.zjw.appmethodorder.MyTextView.onMeasure (II)VMyTextView.java 832 ent   5456681 .......................................com.zjw.appmethodorder.MyTextView.onSizeChanged (IIII)VMyTextView.java 832 ent   5467577 ....................................com.zjw.appmethodorder.MyTextView.onLayout (ZIIII)VMyTextView.java 832 ent   5876623 ...........................................com.zjw.appmethodorder.MyTextView.onDraw (Landroid/graphics/Canvas;)VMyTextView.java 832 ent   6121967 ........com.zjw.appmethodorder.SecondActivity.onStop ()VSecondActivity.java 832 ent   6121986 .........com.zjw.appmethodorder.BaseActivity.onStop ()VBaseActivity.java 832 ent   6123689 ..........com.zjw.appmethodorder.BaseActivity.baseOnStop ()VBaseActivity.java 832 ent   6127522 ........com.zjw.appmethodorder.SecondActivity.onDestroy ()VSecondActivity.java 832 ent   6127679 .........com.zjw.appmethodorder.BaseActivity.onDestroy ()VBaseActivity.java 832 ent   6133301 ..........com.zjw.appmethodorder.BaseActivity.baseOnDestroy ()VBaseActivity.java 

 

OK!發(fā)現(xiàn)是不是很炫酷啊,下面來介紹該庫的原理(求star!!!)

原理

本庫其實并沒有什么黑科技,本庫也沒有java代碼,核心就是2個build.gradle中的task。首先,原理就是基于android sdk中提供的工具----traceview,和dmtracedump。traceview會生成.trace文件,該文件記錄了函數(shù)調(diào)用順序,函數(shù)耗時,函數(shù)調(diào)用次數(shù)等等有用的信息。而dmtracedump 工具就是基于trace文件生成報告的工具,具體用法不細說。

dmtracedump 工具大家一般用的多的選項就是生成html報告,或者生成調(diào)用順序圖片(看起來很不直觀)。首先說說為什么要用traceview,和dmtracedump來作為得到函數(shù)調(diào)用順序的,因為這個工具既然能知道cpu執(zhí)行時間和調(diào)用次數(shù)以及函數(shù)調(diào)用樹(看出函數(shù)調(diào)用順序很費勁)比如android studio是這樣呈現(xiàn).trace文件的解析視圖的

 

 

 

 

或者這樣的

 

 

 

 

是網(wǎng)上找的,侵刪) 用上面這2個圖發(fā)現(xiàn)你要清晰知道函數(shù)調(diào)用看懂了才是見鬼了?;蛘呤褂胐mtracedump 工具解析生成的html長下面這樣(dmtracedump 生成圖片就不說了 生成出的圖片也根本看不出順序這個就略過了)

 

 

 

 

一開始我以為 Method 序列號有戲于是乎沖動的我把帶序號的東西內(nèi)容復制出來寫了一個腳本對他們進行排序代碼如下:

  1.  import java.io.BufferedReader; 
  2. import java.io.FileReader; 
  3. import java.io.IOException; 
  4. import java.util.ArrayList; 
  5. import java.util.Arrays; 
  6. import java.util.Collections; 
  7. import java.util.regex.Matcher; 
  8. import java.util.regex.Pattern; 
  9.  
  10. public class Sort implements Comparable<Sort> { 
  11.  
  12. static String uri = "D:/Application/eclipse/javaworkspace/Testc/JB/1.text"
  13. String str = ""
  14. String content = ""
  15.  
  16. public Sort(String str,String content) { 
  17. super(); 
  18. this.str = str; 
  19. this.content = content; 
  20.  
  21. public static void main(String[] args) throws IOException { 
  22. // TODO Auto-generated method stub 
  23.  
  24. ArrayList<Sort> list = new ArrayList<>(); 
  25.  
  26. BufferedReader in = new BufferedReader(new FileReader(uri)); 
  27. String a = ""
  28.  
  29. while ((a = in.readLine()) != null) { 
  30. //System.out.println(Long.valueOf(getIndexStr(a))); 
  31. if(a.contains("com.zjw.appmethodorder")){ 
  32. list.add(new Sort(getIndexStr(a),a)); 
  33. Collections.sort(list); 
  34. for (Sort sort : list) { 
  35. System.out.println(sort.content); 
  36.  
  37. public static String getIndexStr(String str) { 
  38. String regEx = "(?<=\\[)(\\S+)(?=\\])";// 匹配[]中的數(shù)字 
  39. Pattern p = Pattern.compile(regEx); 
  40. Matcher m = p.matcher(str.trim()); 
  41. while (m.find()) { 
  42. return m.group().trim(); 
  43. return ""
  44.  
  45. @Override 
  46. public int compareTo(Sort o) { 
  47. // TODO Auto-generated method stub 
  48. //return 0; 
  49. return (int) (Long.valueOf(str) - Long.valueOf(o.str)); 
  50.  
  51. }  

 

結(jié)果發(fā)現(xiàn)過濾后的東西序列號是按順序的但是并不是代碼執(zhí)行的邏輯順序。我擦怎么辦,工具代碼也寫了,居然不是我想要的結(jié)果,好在花了一些時間發(fā)現(xiàn)dmtracedump -ho 選項,經(jīng)過研究發(fā)現(xiàn),這玩意輸出的內(nèi)容居然是按邏輯順序從上到下的,于是基于這一點我寫一個項目,其實核心就是2個task完成了了解所有函數(shù)調(diào)用順序的目的。

  1. //核心任務:在captures文件目錄下輸出 基于最新.trace文件的函數(shù)調(diào)用信息的txt版本 
  2.  
  3. //說明:dmtracedump 為 android sdk自帶工具,要執(zhí)行dmtracedump命令則需要先添加環(huán)境變量 
  4.  
  5. task AppOutPutMethodOrder() { 
  6.  
  7.     doLast { 
  8.  
  9.         def capturesDirPath = project.getProjectDir().getParentFile().path + File.separator + "captures"
  10.  
  11.         def capturesDir = new File(capturesDirPath); 
  12.  
  13.         capturesDir.traverse { 
  14.  
  15.             if (it.isFile() && it.name.endsWith(".trace")) { 
  16.  
  17.                 def orderName = it.name.replace("trace""txt"
  18.  
  19.                 def orderFile = new File(capturesDirPath, orderName) 
  20.  
  21.                 orderFile.write(""
  22.  
  23.                 def dmtracedumpDir = getDmtraceDumpDir(); 
  24.  
  25.                 //說明:dmtracedump 為 android sdk自帶工具,要執(zhí)行dmtracedump命令則需要先添加環(huán)境變量 
  26.  
  27.                 def baseComand = dmtracedumpDir + "dmtracedump  -ho " + it.absolutePath + " >> " + orderFile.absolutePath 
  28.  
  29.                 println baseComand 
  30.  
  31.                 String osNameMatch = System.getProperty("os.name").toLowerCase(); 
  32.  
  33.                 if (osNameMatch.contains("windows")) { 
  34.  
  35.                     ("cmd /c start  /b " + baseComand).execute() 
  36.  
  37.                 } else { 
  38.  
  39.                     ["bash""-c", baseComand].execute() 
  40.  
  41.                 } 
  42.  
  43.             } 
  44.  
  45.         } 
  46.  
  47.     } 
  48.  
  49.  
  50.  
  51. /** 
  52.  
  53.  * read the sdk dir from local.properties 
  54.  
  55.  * eg : 
  56.  
  57.  *  sdk.dir = /home/env/sdk 
  58.  
  59.  *  so: 
  60.  
  61.  *   dmtracedump.dir = /home/env/sdk/platform-tools 
  62.  
  63.  * 
  64.  
  65.  * @return the dir which dmtracedump tools exists 
  66.  
  67.  */ 
  68.  
  69. def getDmtraceDumpDir() { 
  70.  
  71.     def rootDir = project.rootDir 
  72.  
  73.     def localProperties = new File(rootDir, "local.properties"
  74.  
  75.     def sdkDir = null
  76.  
  77.     if (localProperties.exists()) { 
  78.  
  79.         Properties properties = new Properties() 
  80.  
  81.         localProperties.withInputStream { instr -> 
  82.  
  83.             properties.load(instr) 
  84.  
  85.         } 
  86.  
  87.         sdkDir = properties.getProperty('sdk.dir'
  88.  
  89.     } 
  90.  
  91.     if (sdkDir == null || !(new File(sdkDir).exists())) { 
  92.  
  93.         sdkDir = android.getSdkDirectory().getAbsolutePath() 
  94.  
  95.     } 
  96.  
  97.     if (sdkDir == null || !(new File(sdkDir).exists())) { 
  98.  
  99.         sdkDir = android.plugin.getSdkFolder().getAbsolutePath() 
  100.  
  101.     } 
  102.  
  103.     def dmtraceDumpToolDir = sdkDir + File.separator + "platform-tools" + File.separator 
  104.  
  105.     if (new File(dmtraceDumpToolDir).exists()) { 
  106.  
  107.         return dmtraceDumpToolDir; 
  108.  
  109.     } 
  110.  
  111.     return "" 
  112.  
  113.  
  114.  
  115. //這里AppFilterMethodOrder 任務其實也不需要 執(zhí)行找到 \captures 目錄找到 base_order.txt 
  116.  
  117. //用Notepad++ 使用正則 先過濾 帶 xit 的行 (我們只關(guān)注ent 行就行,ent代表進入執(zhí)行函數(shù) xit代表退出函數(shù))再過濾掉你不關(guān)心的包名 
  118.  
  119. // Notepad++ 中過濾將會使用到的命令行如下 
  120.  
  121. //^.*xit.*$ //去除掉 含有 xit 字符串的行  然后替換為空 
  122.  
  123. // ^((?!XXX).)*$  //去除不包含XXX的行  然后替換為空 
  124.  
  125. //^\s+   //合并空行  然后替換為空 
  126.  
  127.  
  128. task AppFilterMethodOrder() { 
  129.  
  130.     doLast { 
  131.  
  132.         //TODO 替換為你想要過濾的包名 
  133.  
  134.         def filterPackageName = "com.zjw.appmethodorder" 
  135.  
  136.         if (project.hasProperty("package_name")) { 
  137.  
  138.             filterPackageName = project.getProperty("package_name"
  139.  
  140.         } 
  141.  
  142.         //處理包名 
  143.  
  144.         def filterSignature = filterPackageName.replaceAll("[.]""/"
  145.  
  146.  
  147.         def capturesDirPath = project.getProjectDir().getParentFile().path + File.separator + "captures"
  148.  
  149.         def capturesDir = new File(capturesDirPath); 
  150.  
  151.  
  152.         capturesDir.traverse { 
  153.  
  154.             if (it.isFile() && it.name.endsWith(".txt") && !it.name.contains("--filter")) { 
  155.  
  156.                 def orderName = it.name.replace(".txt""--filter.txt"
  157.  
  158.                 def orderTimeName = it.name.replace(".txt""--timefilter.txt"
  159.  
  160.                 def orderFile = new File(capturesDirPath, orderName) 
  161.  
  162.                 orderFile.write(""
  163.  
  164.                 def orderTimeFile = new File(capturesDirPath, orderTimeName) 
  165.  
  166.                 orderTimeFile.write(""
  167.  
  168.                 it.eachLine { line -> 
  169.  
  170.  
  171.                     if (line.contains(" ent "
  172.  
  173.                         //兼容不同版本traceview 有的是方法包名有的是方法簽名 
  174.  
  175.                     && (line.contains(filterPackageName) 
  176.  
  177.                     || line.contains(filterSignature)) 
  178.  
  179.                     ) { 
  180.  
  181.                         orderFile.append(line + "\n"
  182.  
  183.                     } 
  184.  
  185.  
  186.                     //生成帶xit 和 ent 的trace行 函數(shù)耗時計算方式: xit字符后 數(shù)值 減去 ent字符后的 數(shù)字 (差值就是耗時 單位:微妙) 
  187.  
  188.                     //注意:好像函數(shù)體中含Thread.sleep的計算不準確 
  189.  
  190.                     if (line.contains(filterPackageName) 
  191.  
  192.                             || line.contains(filterSignature)){ 
  193.  
  194.                         orderTimeFile.append(line + "\n"
  195.  
  196.                     } 
  197.  
  198.  
  199.                 } 
  200.  
  201.             } 
  202.  
  203.         } 
  204.  
  205.  
  206.  
  207.     } 
  208.  

 

如何使用

講了一堆原理我們來說說這個庫怎么用吧。

  • 下載utils.gradle到工程根目錄
  • 修改根目錄下build.gradle,增加 apply from: rootProject.getRootDir().getAbsolutePath() + "/utils.gradle" 對utils.gradle的引用,具體可參考本工程根目錄下的build.gradle.
  • 使用下面的詳細介紹生成trace文件
  • 使用下面的命令生成堆棧文件 ./gradlew AppOutPutMethodOrder
  • 上面命令文件內(nèi)容太多時,通過這個命令進行過濾包含需要過濾的字符串 ./gradlew AppFilterMethodOrder -P package_name=com.zjw.appmethodorder

注意:請先確保 anroid sdk 中的dmtracedump 工具加入在你的環(huán)境變量中(Mac同學因為task面板執(zhí)行的bug 需要把gradle添加到環(huán)境變量中)

首先編譯運行項目,然后點擊下圖的時鐘(這是使用工具打trace start 和 end)進行操作,可以參考上文所說的動作簡介(記住你操作想想你的生命周期函數(shù)調(diào)用順序,待會可以和生成的captures目錄下base_order.txt或者生成的order.txt中的函數(shù)順序做做對比)然后再點一次下圖那個時鐘。還有一種記錄trace start 和 end的方式就是在修改代碼,即使用android.os.Debug.startMethodTracing();和android.os.Debug.stopMethodTracing();

 

 

 

 

以上操作完成后即會在captures目錄生成

com.zjw.appmethodorder_2017.03.25_21.41.trace文件,android studio會默認打開一個可視化窗口

 

 

 

 

然后雙擊右側(cè)面板的 AppOutPutMethodOrder任務 (特別注意:用Mac的同學注意了,現(xiàn)在已知雙擊執(zhí)行task會輸出空文件,貌似是studio的BUG,可以使用 ./gradlew AppOutPutMethodOrder執(zhí)行該任務)如下圖

 

 

 

 

這一步完成就將在captures目錄生成和trace文件同名的txt文件(如示例com.zjw.appmethodorder_2017.03.25_21.41.trace),該文件包含所有函數(shù)執(zhí)行順序

等待任務執(zhí)行完成,再雙擊執(zhí)行AppFilterMethodOrder任務 (特別注意:用Mac的同學注意了,現(xiàn)在已知雙擊執(zhí)行task會輸出空文件,貌似是studio的BUG,可以使用 ./gradlew AppFilterMethodOrder -P package_name=com.zjw.appmethodorder執(zhí)行該任務)如下圖窗口

 

 

 

 

該任務目的就是過濾其他非相關(guān)包名,留下自己包名的函數(shù),任務執(zhí)行完成將在captures目錄生成和·trace文件同名+--filter.txt文件(例如示例AppMethodOrder\captures\com.zjw.appmethodorder_2017.03.25_21.41--filter.txt) 如下圖:

 

 

 

 

接下來打開trace文件同名+--filter.txt文件(例如示例AppMethodOrder\captures\com.zjw.appmethodorder_2017.03.25_21.41--filter.txt)就是上文效果中的那樣啦。

關(guān)于擴展和改造

 

 

 

 

這里改成你想要過濾的包名即可。

小工具

Windows 環(huán)境下 可使用tool文件夾下的Method-trace-analysis.jar 直接導入.trace文件,一鍵分析

 

 

 

 

執(zhí)行AppFilterMethodOrder 任務 新增后綴為--filterTime.txt 的文件,用于計算方法耗時

 

 

 

 

如上圖例:MainActivity.onPause方法執(zhí)行耗時為149231-148152 = 1079,最終耗時為 1079μs(微秒) 約為 1毫秒

1.生成帶xit 和 ent 的trace行 函數(shù)耗時計算方式: xit字符后 數(shù)值 減去 ent字符后的 數(shù)字 (差值就是耗時 單位:微妙)

2.注意:函數(shù)體中含Thread.sleep的計算不準確 

責任編輯:龐桂玉 來源: 安卓巴士Android開發(fā)者門戶
相關(guān)推薦

2020-04-10 10:15:29

算法開源Github

2016-10-19 09:00:57

漏洞郵箱秘密

2021-09-16 21:22:15

Flutter系統(tǒng)

2021-05-19 09:40:14

Android 12Android

2023-10-26 11:37:35

函數(shù)Python

2020-05-26 08:38:57

JavaScript語言

2017-10-18 22:01:12

2020-03-27 13:00:14

運維架構(gòu)技術(shù)

2024-09-04 09:00:52

lo?庫邏輯范型

2018-06-20 15:50:38

JDK9JVMJDK10

2022-11-21 18:37:40

漏測BugSOP

2017-12-15 10:50:40

Kotlin語法糖程序員

2013-08-09 09:49:19

開源怎么開源庫開源

2022-04-19 07:38:14

數(shù)組元素指針

2011-06-02 09:08:09

Android 文件

2013-03-27 15:23:51

Android開發(fā)demo下載學習

2017-12-07 15:05:50

全球互聯(lián)網(wǎng)創(chuàng)新峰會

2017-10-26 08:53:38

前端JavaScript函數(shù)式編程

2022-09-01 10:46:02

前端組件庫

2021-08-02 06:49:47

軟件模式結(jié)構(gòu)型
點贊
收藏

51CTO技術(shù)棧公眾號