我正在开发一个带有服务的应用程序,该服务显示通知区域中的计时器的进度(带有进度条和文本)。我已经在下面提取了一个具有相同问题的简单示例。
服务代码:
public class TNService extends Service {
private NotificationManager nm;
private Notification notification;
private RemoteViews remoteView;
@Override
public void onCreate () {
nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification(android.R.drawable.stat_sys_download,
"My notification",
System.currentTimeMillis());
remoteView = new RemoteViews(this.getPackageName(),
R.layout.notification);
remoteView.setImageViewResource(R.id.icon, android.R.drawable.stat_sys_download);
remoteView.setTextViewText(R.id.text, "");
remoteView.setProgressBar(R.id.progress, 100, 0, false);
notification.flags = Notification.FLAG_NO_CLEAR;
notification.contentView = remoteView;
notification.contentIntent = PendingIntent.getActivity(this, 0, new Intent(this,
TNActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
Timer timer = new Timer ();
timer.schedule(new TNTask(this), 0, 200);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
public void updateNotification(int progress) {
remoteView.setProgressBar(R.id.progress, 1000, progress, false);
remoteView.setTextViewText(R.id.text, "Progress: " + progress);
nm.notify(0, notification);
}
}
TimerTask的代码:
public class TNTask extends TimerTask {
private TNService service;
private int progress;
public TNTask(TNService s) {
this.service = s;
this.progress = 0;
}
@Override
public void run() {
progress = (progress + 1) % 1000;
this.service.updateNotification (progress);
}
}
问题是巨大的内存使用量。这是logcat输出:
D/dalvikvm(11985): GC_EXPLICIT freed 1258 objects / 84016 bytes in 1157ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 52216 objects / 1900968 bytes in 130ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 49465 objects / 1805248 bytes in 125ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 53106 objects / 1909992 bytes in 134ms
D/dalvikvm(12008): GC_EXPLICIT freed 1604 objects / 100944 bytes in 90ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 53011 objects / 1937160 bytes in 135ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 49806 objects / 1817992 bytes in 143ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 49016 objects / 1769536 bytes in 135ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 53509 objects / 1941064 bytes in 145ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 49895 objects / 1842312 bytes in 146ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 48728 objects / 1774496 bytes in 150ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 47557 objects / 1701976 bytes in 146ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 53540 objects / 1903808 bytes in 156ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 48997 objects / 1784048 bytes in 158ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 48326 objects / 1776864 bytes in 158ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 47566 objects / 1742488 bytes in 169ms
D/dalvikvm( 85): GC_FOR_MALLOC freed 47606 objects / 1703416 bytes in 170ms
D/dalvikvm( 162): GC_EXPLICIT freed 11238 objects / 641368 bytes in 1064ms
我认为这是太多的内存,过了一段时间后手机会挂起这个输出:
D/dalvikvm( 85): GC_FOR_MALLOC freed 0 objects / 0 bytes in 241ms
I/dalvikvm-heap( 85): Clamp target GC heap from 24.008MB to 24.000MB
I/dalvikvm-heap( 85): Grow heap (frag case) to 24.000MB for 52-byte allocation
I/dalvikvm-heap( 85): Clamp target GC heap from 26.008MB to 24.000MB
D/dalvikvm( 85): GC_FOR_MALLOC freed 0 objects / 0 bytes in 241ms
I/dalvikvm-heap( 85): Clamp target GC heap from 24.008MB to 24.000MB
I/dalvikvm-heap( 85): Grow heap (frag case) to 24.000MB for 24-byte allocation
I/dalvikvm-heap( 85): Clamp target GC heap from 26.008MB to 24.000MB
D/dalvikvm( 85): GC_FOR_MALLOC freed 0 objects / 0 bytes in 247ms
I/dalvikvm-heap( 85): Clamp target GC heap from 24.009MB to 24.000MB
I/dalvikvm-heap( 85): Grow heap (frag case) to 24.000MB for 28-byte allocation
I/dalvikvm-heap( 85): Clamp target GC heap from 26.009MB to 24.000MB
D/dalvikvm( 85): GC_FOR_MALLOC freed 0 objects / 0 bytes in 247ms
I/dalvikvm-heap( 85): Clamp target GC heap from 24.009MB to 24.000MB
任何人都知道如果不使用这么多内存我怎么能这样做?
谢谢!
答案 0 :(得分:10)
我偶然发现了同样的问题......如果我不在服务中“缓存”RemoteView和Notification,但是在“更新”例程中从头开始重新创建它们,这个问题就会消失。是的,我知道它效率不高,但至少手机在10-15分钟后没有重启,因为内存不足。
答案 1 :(得分:2)
尝试使用DDMS转储分配 - 这应该显示正在分配的对象和位置。
我的猜测是进度条在每次调用setProgressBar时都会分配一些位图(每秒5次),这就是通过内存进行搅拌的原因。不清楚的是你为什么要跑出去 - GC似乎在捡起它,所以必须要漏掉一些东西。
答案 2 :(得分:1)
此解决方法的问题在于,如果它是持续通知,它将在状态栏和通知窗格上“跳”,因为其他正在进行的通知会更新。
我尝试了几件事,包括将RemoteView和Notification成员声明为volatile(因为RemoteView是跨线程的),这似乎有效,但只会减慢问题。
我决定使用阻塞成员,并将RemoteView和Notification“缓存”多达X次,然后重新创建它们。
当他们的成员设置为null时,似乎释放了小泄漏。
答案 3 :(得分:0)
我有类似的问题。我有一个Service
,其Notification
提供了一个与文件下载相对应的进度条。在用户点击OutOfMemoryError
将应用程序带到应用程序后大约十秒钟,应用程序会崩溃Notification
。
我发现向构建器添加.setOngoing(true);
解决了这个问题。
public NotificationCompat.Builder setOngoing(boolean ongoing)
设置这是否是持续通知。 正在进行的通知与以下方式的常规通知不同:
正在进行的通知会在通知面板中的常规通知上方进行排序。
正在进行的通知没有“X”关闭按钮,并且不受“全部清除”按钮的影响。
示例:强>
NotificationCompat.Builder builder = new NotificationCompat.Builder(context).setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setContentTitle("Downloading").setContentText("Download in progress...)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setSound(null)
.setDefaults(0)
.setOngoing(true);