Огромное использование памяти в уведомлениях

Я разрабатываю приложение с услугой, которая показывает ход таймера в области уведомлений (с индикатором выполнения и текстом). Ниже я привел более простой пример с той же проблемой.

Код услуги:

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 

Кто-нибудь знает, как я могу это сделать, не используя столько памяти?

Благодаря!

Solutions Collecting From Web of "Огромное использование памяти в уведомлениях"

Я наткнулся на ту же проблему … Кажется, что если я не «кешу» RemoteView и Notification в сервисе, но создаю их с нуля в «обновлении», эта проблема исчезнет. Да, я знаю, что это не эффективно, но, по крайней мере, телефон не перезагружается через 10-15 минут, потому что у него нехватка памяти.

Попробуйте использовать DDMS для выгрузки распределений – это должно показать вам, какие объекты выделяются и где.

Я предполагаю, что индикатор выполнения выделяет некоторые растровые изображения при каждом вызове setProgressBar (5 раз в секунду), и это то, что происходит в памяти. Непонятно, почему вы заканчиваете – GC, кажется, подбирает его, поэтому что-то должно протекать.

Проблема с этим обходным решением заключается в том, что если это постоянное уведомление, оно будет «перескакивать» на панели состояния и панели уведомлений по мере обновления других текущих уведомлений.

Я пробовал несколько вещей, включая объявление элементов RemoteView и Notification как изменчивых (потому что RemoteView является кросс-потоком), который, казалось, работал, но только замедлил проблему.

Я остановился на том, что использовал член затвора и «кэшировал» RemoteView и Notification до X раз, а затем воссоздавал их.

Когда их члены установлены в нуль, небольшая утечка, кажется, освобождается.

У меня была аналогичная проблема. У меня была Service которая представила Notification с индикатором выполнения, который соответствовал загрузке файла. Приложение OutOfMemoryError с OutOfMemoryError , примерно через десять секунд после того, как пользователь нажал 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);