2012-09-26 65 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; 
}