2012-09-26 73 views
1

我寫了一個android服務,它計算安裝在手機上的應用程序列表並獲取應用程序名稱。ApplicationInfo LoadLabel增加我服務的內存消耗(android)

代碼大致是這樣的:

List<PackageInfo> appListInfo = pm.getInstalledPackages(0); 
       for (PackageInfo p : appListInfo) { p.applicationInfo.loadLabel(pm).toString());           }  

我所觀察到的是,呼籲所有packageInfo對象時,loadLabel功能增加了內存消耗了很多。執行此代碼時,我的服務通常需要3至5 MB,峯值爲16 MB。

雖然,此內存得到釋放,最終(GC運行時)和服務追溯到3-5MB,我想知道是否可以避免這種秒殺,而且還能達到我的目標

原因我想這是,我打算推出這個應用程序輕量級,這是不可能的,如果這繼續發生。

回答

0

內存消耗不應該在這裏關注你,因爲大的高峯並不意味着當時不能回收內存。這可能意味着垃圾回收沒有必要,因爲有足夠的空閒內存。使用更多的內存甚至可以讓事情變得更快,使用可用內存沒有負面影響。

但是你可以嘗試以下方法,以確保對象可以更早獲得GC'd:

List<PackageInfo> packages = pm.getInstalledPackages(0); 
for (int i = 0; i < packages.size(); i++) { 
    PackageInfo p = packages.set(i, null); 
    p.applicationInfo.loadLabel(pm).toString(); 
} 
packages = null; 

這可能的情況下,幫助PackageInfo對象保留額外的內存,一旦你撥打loadLabel方法。使用上述方法時,在信息加載完成後,對這些信息的引用將被清除,而在您的方法中,它們全部仍被列表引用,並且只有在整個循環完成後才能GC'd,並且packages可以GC'd。

我打算推出這個應用程序輕量級,這是不可能的,如果這種情況繼續發生。

我懷疑用戶是否會監視內存使用率的尖峯。對記憶的典型認知也是錯誤的。免費內存=浪費的資源,如果你擁有它,不會加速你的手機。營銷!=技術細節:)

1

我有同樣的問題。我的應用程序通常使用32mb尖峯到50mb。 loadLabel在可運行的程序中被調用,該程序每隔x秒/分鐘從服務中調用一次。我已經看到內存高達90MB。我信任GC,但我的應用程序記錄數據,並且需要始終運行,所以它非常有資格從操作系統終止。

我的解決方案已將空的ApplicationInfo然後調用System.gc()釋放內存。這樣我的應用程序保持在32mb。

如果有人有更好的方法,請通知我們。

0

它永遠不會太晚回覆

什麼幕後發生的事情就是Android負載每個應用的APK,因此它的資源,以獲得從資源的文本。

儘管在GC發生之前資源不會關閉,但它周圍會有一些消耗,只有當您擔心增加的規模時纔會有一些成本。

您可以使用隱藏的API並自行加載資源並在完成後刪除它們。

... 
Resources res; 
AssetManager assetMgr; 
DisplayMetrics metrics = getDisplayMetricsLocked(null, false); 
Configuration config = new Configuration(); 
List<PackageInfo> packages = pm.getInstalledPackages(0); 
int tmpResId; 
for (PackageInfo p: packages){ 
    tmpResId = p.applicationInfo.labelRes; 
    if(tmpResId == 0){ 
     p.applicationInfo.setAppName(p.applicationInfo.nonLocalizedLabel); 
    }else { 
     //hidden API's here 
     assetMgr = new AssetManager(); 
     if(assetMgr.addAssetPath(p.applicationInfo.sourceDir) == 0){ 
     if(assetMgr.addAssetPath(p.applicationInfo.publicSourceDir) == 0){ 
      continue; 
     } 
     } 
     res = new Resources(assetMgr, metrics, config); 
     //Get your label here 
     ...res.getText(tmpResId); 
     res.getAssets().close(); 
    } 

} 
assetMgr = null; 
res = null; 
... 

static DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) { 
    DisplayMetrics dm = new DisplayMetrics(); 
    Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay(); 
    d.getMetrics(dm); 
    return dm; 
}