如何有效的清除Android中無用的資源(靜態程式碼分析)

影響身邊的人發表於2016-08-24

最近公司要做這個,簡單調研了一下,現有的大多數部落格也比較舊了,不太合適,總結了這麼幾個方式吧,一起來學習下。

為什麼要清除Android中這些資源呢

是這樣的,今天收到的郵件裡,有這麼一條任務:

資源優化

  軟體中無用的圖片和佈局檔案,找到並驗證是否無用.
       這個需要設計一套工具進行分析(自行設計最好或者第三方)複製程式碼

嗯,好吧...說笑了! 下面是正題↓↓↓↓

其實隨著專案不斷更新,需求不斷變動,一改再改,UI一調再調,結果就是專案中一堆已經用不到但卻沒有清理的垃圾資源,不說工程大小問題,對新進入專案的人或看其他模組的程式碼的人來說,這些沒清理的資源可能也可能會帶來困擾,所以最好還是清理掉這些垃圾,對於一個稍微大一點的工程來說,手工清理明顯是不現實的,這就需要一個方法做這些事情。

知識整合

看了很久,總結了一下,我能找到的市面上大概有8種方法來做這件事,覺得裡面比較好用的整理一下分為5點,時間原因肯定不能全試啦,因為選出最合適的方法就要開始寫成公司自己專門的工具了,簡單說一下:

1.看到的第一個方法就是用SDK提供的程式碼檢查工具Android lint

Android lint 刪除無用圖片檔案和配置檔案

  • Android lint 在 Android sdk tools 當中 配好環境變數(知道了Lint,這個工具非常強大!強烈推薦研究一下)
  • 輸入:lint --check "UnusedResources" /Users/baozi/Dev/android/android > result.txt(可以把無用資源資訊輸出到result檔案)
  • 開啟result檔案檢視資訊,會發現在哪一行,叫什麼,都會給出相應的評價。
  • 刪除:程式碼如下(非常重要)!借用文中的一句話就是:手工逐條刪除 並不符合程式猿三大優秀品質 : 懶惰 沒有耐心 驕傲
/** 
 * 刪除 未使用的冗餘資源(圖片 xml佈局) 
 *  
 * @param b 
 *  
 *            false 顯示資源列表 
 *  
 *            true 顯示資源列表 並刪除資源 
 *  
 * @throws Exception 
 */  
private static void init(boolean b) throws Exception {  

    String encoding = "UTF-8"; // 字元格式  
    String projectPath = "/Users/baozi/Dev/shihui/android/";//Android工程所在地址  
    String filePath1 = "/Users/baozi";//result的所在路徑  
    File file = new File(filePath1, "result.txt");//獲取result.txt 檔案 生成地址  
    if (file.isFile() && file.exists()) { // 判斷檔案是否存在  
        InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);// 考慮到編碼格式  
        BufferedReader bufferedReader = new BufferedReader(read);  
        String line = null;  
        while ((line = bufferedReader.readLine()) != null) {  
            if (line.contains("UnusedResources") && !line.contains("res/value") && !line.contains("appcompat")  
                    && !line.contains("res/xml")) {  
                // System.out.println(line);  
                int end = line.indexOf(":");  
                if (end != -1) {  
                    String file_end = line.substring(0, end);  
                    String f = projectPath + file_end;  
                    System.out.println(f);  
                    if (b) {  
                        new File(f).delete();  
                        System.out.println("刪除成功");  
                    }  
                }  

            }  

        }  
        read.close();  

    }  
}複製程式碼
  • projectPath : Android工程在硬碟中的位置
  • filePath1 : lint 執行結果 result.txt 所在的位置

方法 引數 傳入false 僅列印結果 傳入true 列印結果 並刪除檔案

填入正確的地址 就能批量執行刪除未使用的 佈局 & 圖片 資源 (UnusedResources)

如果想要刪除其它操作 請修改 篩選條件
if (line.contains("UnusedResources") && !line.contains("res/value") && !line.contains("appcompat") && !line.contains("res/xml")

使用心得: 迴圈使用3-6次 能完成 刪除全部未使用的資源 但是有些廢棄的模組 存在程式碼以來關係 需要手工判斷刪除 缺點:判斷不準確


2.一個自動清理Android專案無用資源的工具類及原始碼

原文點此處

優點:把上個方法中找出的無用資源的資訊,再刪除,整個步驟封裝成了一個程式,並且對原GITHUB專案進行了優化:對用到的如string、style等資源進行了處理。 步驟程式碼較長,就不貼了,詳細看原文。


3.Android Studio利用Gradle刪除沒有使用到的資源和程式碼檔案

原文點此處

利用Gradle來優雅的去除沒有用到的資原始檔:

android {
        buildTypes {
            release {
                minifyEnabled true
                shrinkResources true
            }
        }
    }複製程式碼

缺點:很多沒有用到的類還是會被打包進去。去除無效程式碼的功能要依賴於混淆,混淆又是一個耗時的操作,還是沒有徹底解決打包慢的問題。

當然也可以做一些忽略無用的程式碼優化,所以感覺還不錯。


4.利用python自動清除Android工程中的多餘資源

原文點此處

該文是博主直接在公司使用的方法,如下:

#################################################
#環境: win + python 2.7
#作者:馬波
#郵箱:mabo02@baidu.com
#部門:hao123-無線
#說明:首次使用時lint分析會耗幾分鐘,請耐心等待。
#      使用前先clean工程,確保工程bin下重新生成dex,
#      以便lint進行分析。如果要lint重新分析多餘
#      資源,需要刪掉(2)txt記錄檔案,(1)(3)(4)需要
#      根據我們的實際工程手動設定。
#      如果清除資源後,工程缺少檔案而報錯(極少
#      情況),嘗試通過svn恢復該檔案即可。
#################################################
import subprocess    
import re
import os
import time
import thread  

#(1)工程位置
projectPath="D:\/hao123\/code\/client-android"
#(2)lint輸出txt記錄檔案
txt="D:\/hao123_unused_res.txt"
#(3)正規表示式,清除drawable和layout下多餘的jpg/png/xml,
#   並且排除以sailor_|wenku_|zeus_|bdsocialshare_|floating_life_|weather_info_icon_|anthology_開頭的檔案
regex = re.compile(r"^res\\(drawable(-land)?(-[xn]?[mhlo](dpi))|layout)?\\(?!(sailor_|wenku_|zeus_|bdsocialshare_|floating_life_|weather_info_icon_|anthology_))[0-9a-zA-Z_\.]*\.(jpg|png|xml)", re.IGNORECASE)
#(4)lint.bat的位置
lint="D:\/sdk\/tools\/lint.bat"

isgotTxt=False
def timer(interval):  
    while not isgotTxt:
        print 'Lint is analyzing: %s'%time.ctime()  
        time.sleep(interval)

if not os.path.exists(txt):
    thread.start_new_thread(timer, (5,))
    cmd=lint+' --check "UnusedResources" "'+ projectPath +'" >'+txt
    p = subprocess.Popen(cmd, shell = True,stdout = subprocess.PIPE,stdin = subprocess.PIPE,stderr = subprocess.PIPE)        
    p.wait()

fobj=open(txt,'r') 
isgotTxt=True
i=0
j=0
for line in fobj:
    #print str(i)+":"+line
    match=regex.match(line)
    if match:
        i=i+1
        filename=projectPath+"\/"+match.group().replace('\\',"\\/")
        try:
            print filename
            os.remove(filename)
            j=j+1
            print "was deleted!"
        except WindowsError:
            print "is not exists"
            pass

print "Total Unused Resources = "+str(i)
print "Total deleted Resources = "+str(j)複製程式碼

雖然系統不一樣,還是打算寫python指令碼來試一下。


5.還有這幾篇有關與AndroiStudio圖形化操作 以及一個Android Clear工具,以及用jar的方式都大同小異了,下面做個總結,下面幾篇文章也是有不同的幫助

多方法批量刪除Android中無用的資源(更新Android Studio2.1工具) 去除無用資原始檔最方便的方法

清除Android工程中沒用到的資源 去除無用java程式碼

清理你的Android程式碼

找出程式碼中已有的BUG —— FindBugs

去掉多餘的jar包 —— ClassPath Helper

一定要非常注意的點:

(1)被無用資源引用的資源不會被視為無用資源,所以需要重複執行多次,保證清除乾淨。

(2)刪除資原始檔之前要先刪除無用java程式碼,否則容易報錯,因為程式碼中還(可能)存在引用.

(3)一定要提交之後,再做備份在清除資源,你懂~


我的思路

1. 清除Java程式碼

2. 找出無用資源

3. 按需清理

具體如下:

清除Java程式碼

  • 安裝Eclipse的UCDetector外掛,對工程執行檢查,結果會輸出到一個文字檔案中,同樣是每個問題一行.
  • 處理沒用到的類檔案
String reportPath = "**/ucdetector_reports/UCDetectorReport_001.txt";
BufferedReader reader = new BufferedReader(new FileReader(reportPath));
String line;
int count = 0;
while((line = reader.readLine()) != null) {
    if (line.contains("Class") && line.contains("has 0 references") && !line.contains("Method")[ && other conditions]) {
        count++;
        int end = line.indexOf(".<init>");
        if (end != -1){
            String className = line.substring(0, end);
            System.out.println(className);
        }
    }
}複製程式碼
  • 過濾不想刪除的

找出無用資源 && 按需清理

在最新的版本(Studio2.1)中,lint已經可以自行刪除無用資源,這樣的話,我們的python指令碼也不需要寫了(2.1以下還是自行寫指令碼),具體操作如下:

  • Ctrl+Shift+Alt+I 彈出一個框,輸入UnusedResources,彈出下圖

  • 點選OK,出來下圖

我們選擇Remove All Unused Resources。片刻後(工程大可能會比較久,1-2min?)彈出一個確認對話方塊,確認之 。


上述提到的LINT:

靜態程式碼分析工具,無需執行,無需測試用例

掃描整個專案,分析以下潛在的問題,分類指出問題描述、問題位置,並提供合理的修改建議(這是才是關鍵啊,不管有木有大問題,看看這些問題及描述,也能過把癮啊):

1)效能 佈局效能(以前是 layoutopt工具,可以解決無用佈局、巢狀太多、佈局太多、overdraw) 其他效能(如:draw/layout 時進行物件的宣告等)

2)未使用到資源、資源缺少(不同資源的適配)

3)有更高效能的資源替換 ---- eg:SparseBooleanArray SparseIntArray

4)國際化問題(硬編碼)

5)圖示的問題(重複的圖示,錯誤的大小)

6)可用性問題(如不指定的文字欄位的輸入型)

7)manifest檔案的錯誤 -- 未註冊activity service等等

8)記憶體洩露 --- 如:handle的不當使用 。

9)佔記憶體的資源及時回收 --- 如:TypedArray未回收資源等

附:

Android效能優化之LINT使用總結

Improve Your Code with Lint google文件

相關文章