天天看點

清除Android工程中沒用到的資源 清理資源檔案 清理Java檔案 總結

項目需求一改再改,ui一調再調,結果就是項目中一堆已經用不到但卻沒有清理的垃圾資源,不說工程大小問題,對新進入項目的人或看其他子產品的代碼的人來說,這些沒清理的資源可能也可能會帶來困擾,是以最好還是清理掉這些垃圾,對于一個稍微大一點的工程來說,手工清理明顯是不現實的,這就需要一個方法做這些事情。

要清理沒用的資源,首要的工作當然是找到他們,我們知道anroid sdk中有一個工具叫lint,可以幫助我們檢視工程中存在的問題,其中有一項功能就是查找沒用到的資源,這樣這一步就簡單了,直接對需要清理的工程執行以下指令:

[java] view

plaincopy

lint --check "unusedresources" [project_path] > result.txt  

執行完以上指令後工程中關于unusedresources的問題就都儲存到result.txt了,先來看一下result.txt的内容

res/values/arrays.xml:202: warning: the resource r.array.msg_my_friend_category_items appears to be unused [unusedresources]  

    <string-array name="msg_my_friend_category_items">^m  

                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  

res/layout/back_up_level_list.xml: warning: the resource r.layout.back_up_level_list appears to be unused [unusedresources]  

res/layout/backup_list.xml: warning: the resource r.layout.backup_list appears to be unused [unusedresources]  

res/layout/backup_listview_item.xml: warning: the resource r.layout.backup_listview_item appears to be unused [unusedresources]  

可以看到列出了沒用到的layout及沒用到的values值等資訊。有了這些資訊,接下來需要做的就是分析這些資訊了,手工分析不太現實,因為這個檔案可能會非常大,比如我執行上述指令後檔案就有2212行,這種事情,當然是交給計算機解決了。

仔細看生成的文本中的内容會發現結果是按行輸出的,每個問題是單獨的一行,而且每一行中的内容也很有規律

file_path[:line]: warning: info [unusedresources}

是以還是可以很友善地得到哪個檔案甚至哪行有問題的,我處理的時候隻清理了沒用的檔案,像上面的res/values/arrays.xml:202就沒有管,下面看下怎麼清除沒用到的資源檔案。

string projectpath = "***";  

bufferedreader reader = new bufferedreader(new filereader("/home/angeldevil/result.txt"));  

string line;  

int count = 0;  

while((line = reader.readline()) != null) {  

    if (line.contains("unusedresources") && !line.contains("res/value") && !line.contains("appcompat")) {  

        count++;  

        int end = line.indexof(":");  

        if (end != -1){  

            string file = line.substring(0, end);  

            string f = projectpath +file;  

            system.out.println(f);  

            new file(f).delete();  

        }  

    }  

}  

程式非常簡單,就幾行代碼,就是讀取result.txt檔案的每一行,根據自己需要的條件過濾掉不需要處理的行(比如我隻想清理anim、drawable及layout,是以過濾掉res/value目錄下的資訊,并且忽略appcompat相關的資訊),每一行":"前的字元串就是檔案名,找到了檔案名就好處理了,直接删除,或者列印出來,或者寫到一個檔案裡以再次确認是否确認要删除,當把結果寫到一個檔案後我們就可以檢視這個檔案是否有現在沒用到但仍不想删除的檔案,如果有,處理方法也很簡單,去掉這一行或簡單地做個标記,如前面打#,然後再讀取這個檔案把沒做标記的行對應的檔案删除就行了。

看起來很簡單,但是有幾點需要注意:

有些layout檔案,可能你之前用了他們,并在相應的java檔案中用了這個layout布局中的id,如對某些id的控件設定了onclicklistener,并在onclick的switch...case中引用了這些id,但最後又不用這個layout了,這時這個layout就是unusedresource,但是以前引用它的java代碼中對這個layout中的某些id的引用還沒清除,此時删掉這個layout就會報錯,你可以選擇清理報錯的java代碼,因為它們其實時dead code。或者每次清理一部分資源檔案,如先清理layout,再清理drawable,對于每一項也可以根據檔案名的規則每次再清理一小部分,如隻清理res/layout中以item_of開頭的檔案。

lint的分析貌似是不完全準确的,或者說不夠智能,比如有一個drawable隻被一個layout引用,而這個layout又是unused的,lint可能不會發現這個drawable是unused,這就需要我們多次重複執行前面的步驟,直到count為0。

lint隻能分析資源檔案,即res目錄下的檔案,如果要分析java檔案還需要其他方法,而且,有可能某個資源檔案被某java檔案引用,而這個java檔案又是unused,這樣這個資源檔案就會逃過lint的檢查,是以我們最好先清理了java檔案再清理資源檔案。

首先還是要找到未用到的檔案,還是利用工具,我用的是ucdetector,即unused code detector,使用方法就不說了,直接google一下。

安裝eclipse的ucdetector插件,對工程執行檢查,這個需要的時間可能會很長,我當時檢查了兩個小時。。同lint一樣,結果會輸出到一個文本檔案中,同樣是每個問題一行,是以隻要行分析就行了,比如這樣:

com.**.sampleadapter.<init>(sampleadapter.java:18)  class "sampleadapter" has 0 references        sampleadapter org.ucdetector.analyzemarkerreference  

com.**.sampleadapter.<init>(sampleadapter.java:56)  change visibility of member class "sampleadapter.viewholder" to private - may cause compile errors!   sampleadapter.viewholder      org.ucdetector.analyzemarkervisibilityprivate  

可以看到,檢測結果中包含很多資訊,如某個類沒被用到,某個方法的可見性太大等,同樣的,現在隻處理沒用到的類檔案,其他不管了。

string reportpath = "**/ucdetector_reports/ucdetectorreport_001.txt";  

bufferedreader reader = new bufferedreader(new filereader(reportpath));  

    if (line.contains("class") && line.contains("has 0 references") && !line.contains("method")[ && other conditions]) {  

        int end = line.indexof(".<init>");  

            string classname = line.substring(0, end);  

            system.out.println(classname);  

通過以上代碼基本上就能找到沒用到的類了,還是建議不直接删除而是把結果輸出出來,因為結果輸出來以後你會發現很多檔案你是不想删除的,如:

com.nostra13.universalimageloader.core.assist.disccacheutil.<init>(disccacheutil.java:31)       class "disccacheutil" has 0 references  disccacheutil   org.ucdetector.analyzemarkerreference   sergey tarasevich (nostra13[at]gmail[dot]com)  

某些類庫中的檔案也可能會被檢測出來,對于這種直接在if條件中過濾掉就好了,也可能自己的一些檔案暫時沒用到但不想删除,從結果中過濾就好了。

清理資源就兩個步驟:

找到未用到的資源

按需清理這些資源

通過ucdetector和lint基本上就可以檢測到項目中unusedresource相關的問題了,一般像方法可見性,某個方法沒用到這種問題,不處理也罷,改到相應的檔案時手工處理算了,主要處理的就是某些檔案或類沒被用到,有檢測報告,分析下報告就行了。這種報告一般是每行報告一個問題并且每行的文字是有規律的(工具生成的肯定有規律),按規律過濾出我們需要的資訊就行了

繼續閱讀