ApplicationInfo LoadLabel增加我的服务(android)的内存消耗
我编写了一个android服务,它计算手机上安装的应用程序列表,并获取应用程序名称 代码大致如下所示:ApplicationInfo LoadLabel增加我的服务(android)的内存消耗,android,memory-management,Android,Memory Management,我编写了一个android服务,它计算手机上安装的应用程序列表,并获取应用程序名称 代码大致如下所示: List<PackageInfo> appListInfo = pm.getInstalledPackages(0); for (PackageInfo p : appListInfo) { p.applicationInfo.loadLabel(pm).toString());
List<PackageInfo> appListInfo = pm.getInstalledPackages(0);
for (PackageInfo p : appListInfo) { p.applicationInfo.loadLabel(pm).toString()); }
List appListInfo=pm.getInstalledPackages(0);
对于(PackageInfo p:appListInfo){p.applicationInfo.loadLabel(pm.toString());}
我所观察到的是,当对所有packageInfo
对象调用loadLabel
函数时,会大大增加内存消耗。我的服务通常需要3-5MB,执行此代码时会达到16mb
虽然最终会释放内存(当GC运行时),并且服务返回到3-5mb,但我想知道是否可以避免这个峰值并仍然实现我的目标
我想要这样做的原因是,我计划将此应用程序作为轻量级产品进行营销,如果这种情况持续发生,这是不可能的。内存消耗不应该让您担心,因为大峰值并不自动意味着此时无法回收内存。这可能只是意味着垃圾收集是不必要的,因为有足够的可用内存。使用更多的内存甚至可以使事情变得更快,而使用空闲内存没有负面影响 但您可以尝试以下方法以确保对象可以更早地获得GC:
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;
List packages=pm.getInstalledPackages(0);
对于(int i=0;i
如果调用loadLabel
方法后,PackageInfo
对象保留额外的内存,这可能会有所帮助。在上述方法中,在加载信息后,对这些信息的引用将被清除,而在您的方法中,它们都将被列表引用,并且只有在整个循环完成后才能进行GC,并且可以对包进行GC
我计划以轻量级的方式推广这个应用程序,如果这种情况持续下去,这是不可能的
我怀疑用户是否会监控内存使用情况以防出现峰值。另外,典型的记忆感知是错误的。空闲内存=浪费资源,如果你有手机,就不会加速。营销!=技术细节:)此处的内存消耗不应引起您的关注,因为大峰值并不自动意味着此时无法回收内存。这可能只是意味着垃圾收集是不必要的,因为有足够的可用内存。使用更多的内存甚至可以使事情变得更快,而使用空闲内存没有负面影响 但您可以尝试以下方法以确保对象可以更早地获得GC:
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;
List packages=pm.getInstalledPackages(0);
对于(int i=0;i
如果调用loadLabel
方法后,PackageInfo
对象保留额外的内存,这可能会有所帮助。在上述方法中,在加载信息后,对这些信息的引用将被清除,而在您的方法中,它们都将被列表引用,并且只有在整个循环完成后才能进行GC,并且可以对包进行GC
我计划以轻量级的方式推广这个应用程序,如果这种情况持续下去,这是不可能的
我怀疑用户是否会监控内存使用情况以防出现峰值。另外,典型的记忆感知是错误的。空闲内存=浪费资源,如果你有手机,就不会加速。营销!=技术细节:)我也有同样的问题。我的应用程序,通常使用32mb到50mb的峰值。loadLabel正在runnable中调用,该服务每x秒/分钟调用一次。我看到内存高达90mb。我信任GC,但我的应用程序记录数据,并且需要一直运行,因此它非常适合从操作系统终止 我的解决方案是将ApplicationInfo设置为null,然后调用System.gc()来释放内存。这样,我的应用程序保持在32mb
如果有人有更好的方法,请通知我们 我也有同样的问题。我的应用程序,通常使用32mb到50mb的峰值。loadLabel正在runnable中调用,该服务每x秒/分钟调用一次。我看到内存高达90mb。我信任GC,但我的应用程序记录数据,并且需要一直运行,因此它非常适合从操作系统终止 我的解决方案是将ApplicationInfo设置为null,然后调用System.gc()来释放内存。这样,我的应用程序保持在32mb
如果有人有更好的方法,请通知我们 回复永远都不晚 幕后发生的事情是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;
}
。。。
资源和资源;
资产管理人资产管理人;
DisplayMetrics metrics=getDisplayMetricsLocked(null,false);
配置配置=新配置();
列表包=pm.getInstalledPackages(0);
int-tmpResId;
对于(PackageInfo p:软件包){
tmpResId=p.applicationInfo.labelRes;
如果(tmpResId==0){
p、 applicationInfo.setAppName(p.applicationInfo.nonLocalizedLabel);
}否则{
//隐藏的API在这里
assetMgr=新的AssetManager();
if(assetMgr.addAssetPath(p.applicationInfo.sourceDir)==0){
if(assetMgr.addAssetPath(p.applicationInfo.publicSourceDir)==0){
持续
}
}
res=新资源(资产管理组、指标、配置);
//把你的标签拿过来
…res.getText(tmpResId);
res.getAssets().close();