【问题标题】:Huge memory usage in notifications通知中的大量内存使用
【发布时间】:2010-08-31 11:50:39
【问题描述】:

我正在开发一个带有服务的应用程序,该服务在通知区域显示计时器的进度(带有进度条和文本)。我在下面提取了一个具有相同问题的更简单的示例。

服务代码:

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

谁知道不占用这么多内存怎么办?

谢谢!

【问题讨论】:

标签: java android service notifications


【解决方案1】:

我偶然发现了同样的问题......似乎如果我不在服务中“缓存”远程视图和通知,而是在“更新”例程中从头开始重新创建它们,这个问题就会消失。是的,我知道它效率不高,但至少手机在 10-15 分钟后没有重新启动,因为它内存不足。

【讨论】:

  • 我遇到了完全相同的问题,我的手机要么崩溃(HTC 传说),要么部分操作系统崩溃(索尼爱立信 Xperia Mini Pro)。在每次更新时重新创建 RemoteView 解决了这个问题。
【解决方案2】:

尝试使用 DDMS 转储分配 - 这应该会显示正在分配的对象以及分配的位置。

我的猜测是,进度条会在每次调用 setProgressBar 时分配一些位图(每秒 5 次),这就是在内存中搅动的东西。不清楚的是为什么你会用完 - GC 似乎正在捡起它,所以肯定有什么东西泄漏了。

【讨论】:

  • 我在通知中使用了一次进度条,我体验到手机在尝试更新进度时变得很慢。所以,我不得不降低更新频率。
  • 是的!这也是我的解决方案,但我不知道如何避免或减少这种行为。
【解决方案3】:

此解决方法的问题在于,如果它是一个持续通知,它会随着其他持续通知的更新而“跳跃”在状态栏和通知窗格上。

我尝试了几件事,包括将 RemoteView 和 Notification 成员声明为 volatile(因为 RemoteView 是跨线程的),这似乎可行,但只会减缓问题的速度。

我决定使用 choke 成员,并将 RemoteView 和 Notification 最多“缓存”X 次,然后重新创建它们。

当他们的成员设置为空时,小泄漏似乎被释放了。

【讨论】:

    【解决方案4】:

    我遇到了类似的问题。我有一个Service,它显示了一个Notification,带有一个与文件下载相对应的进度条。在用户单击Notification 将他们带到应用程序后大约十秒钟,应用程序将崩溃并显示OutOfMemoryError

    我发现将.setOngoing(true); 添加到 Builder 可以解决这个问题。

    public NotificationCompat.Builder setOngoing(布尔值持续)

    设置这是否是持续通知。 持续通知与常规通知在以下方面有所不同:

    • 正在进行的通知在通知面板中排在常规通知的上方。

    • 正在进行的通知没有“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);
    

    【讨论】:

      猜你喜欢
      • 2018-02-21
      • 2018-04-18
      • 2017-08-08
      • 2014-04-02
      • 2014-04-06
      • 1970-01-01
      • 2012-01-13
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多