最近公司要做這個,簡單調研了一下,現有的大多數部落格也比較舊了,不太合適,總結了這麼幾個方式吧,一起來學習下。
為什麼要清除Android中這些資源呢
是這樣的,今天收到的郵件裡,有這麼一條任務:
資源優化
軟體中無用的圖片和佈局檔案,找到並驗證是否無用.
這個需要設計一套工具進行分析(自行設計最好或者第三方)複製程式碼
嗯,好吧...說笑了! 下面是正題↓↓↓↓
其實隨著專案不斷更新,需求不斷變動,一改再改,UI一調再調,結果就是專案中一堆已經用不到但卻沒有清理的垃圾資源,不說工程大小問題,對新進入專案的人或看其他模組的程式碼的人來說,這些沒清理的資源可能也可能會帶來困擾,所以最好還是清理掉這些垃圾,對於一個稍微大一點的工程來說,手工清理明顯是不現實的,這就需要一個方法做這些事情。
知識整合
看了很久,總結了一下,我能找到的市面上大概有8種方法來做這件事,覺得裡面比較好用的整理一下分為5點,時間原因肯定不能全試啦,因為選出最合適的方法就要開始寫成公司自己專門的工具了,簡單說一下:
1.看到的第一個方法就是用SDK提供的程式碼檢查工具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程式碼
一定要非常注意的點:
(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未回收資源等
附:
Improve Your Code with Lint google文件