Обновление виджета Android из сервиса - утечка памяти? - PullRequest
1 голос
/ 11 декабря 2010

У меня есть Service, и я хочу, чтобы он обновлял виджет на рабочем столе каждую секунду. Поэтому Служба прослушивает OnTimerEvent, который отправляется TimeController каждую секунду. TimeController - это одиночный объект, содержащий обработчик, который запускает mUpdateTimeTask:

public class TimeController {
    private long startTime = -1;
    // ... attributes ... listeners etc
    private Runnable mUpdateTimeTask = new Runnable() {
        public void run() {
            TimeController.this.notify(new TimerUpdateEvent(this));
            startTime += DateUtils.SECOND_IN_MILLIS;
            mHandler.postAtTime(this, startTime);
        }
    };

    public void startTimer() {
        // if not already running
        if (startTime == -1) {
            startTime = SystemClock.uptimeMillis();
            mHandler.removeCallbacks(mUpdateTimeTask);
            mHandler.postDelayed(mUpdateTimeTask, 0);
        }
    };
    // ...
}

Это все работает, и виджет обновляется, но в Logcat я вижу:

12-10 22:06:42.825: DEBUG/dalvikvm(1738): GC freed 17488 objects / 651080 bytes in 112ms
12-10 22:06:44.035: DEBUG/dalvikvm(1738): GC freed 17479 objects / 650832 bytes in 172ms
12-10 22:06:45.205: DEBUG/dalvikvm(1738): GC freed 17428 objects / 649744 bytes in 97ms
12-10 22:06:46.315: DEBUG/dalvikvm(1738): GC freed 17463 objects / 650656 bytes in 86ms
12-10 22:06:47.725: DEBUG/dalvikvm(1738): GC freed 17793 objects / 663872 bytes in 85ms
12-10 22:06:48.985: DEBUG/dalvikvm(1738): GC freed 17026 objects / 633944 bytes in 176ms
12-10 22:06:50.145: DEBUG/dalvikvm(1738): GC freed 17492 objects / 651352 bytes in 89ms
12-10 22:06:51.674: DEBUG/dalvikvm(1738): GC freed 17435 objects / 650320 bytes in 105ms
12-10 22:06:52.934: DEBUG/dalvikvm(1738): GC freed 17519 objects / 652584 bytes in 109ms
12-10 22:06:54.234: DEBUG/dalvikvm(1738): GC freed 17487 objects / 650920 bytes in 90ms
12-10 22:06:55.645: DEBUG/dalvikvm(1738): GC freed 17685 objects / 659448 bytes in 91ms

И мне не нравится то, что я вижу ...: -)

public class MyService extends Service implements TimerUpdateListener {
    @Override
    public void onCreate() {
        timeController = TimeController.getInstance();
        timeController.addListener(this);
        timeController.startTimer();

        appWidgetManager = AppWidgetManager.getInstance(this);
        remoteViews = new RemoteViews(this.getPackageName(), R.layout.widget_2x1);
        projectWidget = new ComponentName(this, ProjectWidget.class);

        super.onCreate();
    }
    @Override
    public void onTimerUpdate(TimerUpdateEvent e) {
        updateWidgetViews();
    }

    private void updateWidgetViews() {
        // only update widgets if some exist
        if (appWidgetManager.getAppWidgetIds(projectWidget).length > 0) {
            remoteViews.setTextViewText(R.id.time, MyDateUtils.timeLeftAsString(project.getInCurrentLevelSince()));

            appWidgetManager.updateAppWidget(projectWidget, remoteViews);
        }
    }
}

Если я закомментирую remoteViews.setTextViewText(...), сообщения GC не появятся. Так как же я могу обновить представление без такой большой утечки памяти?

Спасибо!

1 Ответ

4 голосов
/ 11 декабря 2010

У меня есть служба, и я хочу, чтобы она обновляла виджет на рабочем столе каждую секунду.

Пожалуйста, не делайте этого.Механизм виджетов приложения предназначен для вещей, которые обновляются гораздо реже - скажем, раз в полчаса.Если вы сделаете это, вы забьете батарею пользователя в кражу и похитите процессорное время из его приложения на переднем плане (например, сократите частоту кадров в той игре, в которую играют).Пожалуйста, не имейте службу, единственная миссия которой состоит в том, чтобы отслеживать время.Вместо этого используйте AlarmManager.

Так как я могу обновить представление, не имея такой большой утечки памяти?

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

О, я забыл: да, я знаю, что обновления виджетов каждую секунду не рекомендуется, но мне действительно нужно обновление по крайней мере каждые 10 секунд.

Ваши пользователи действительно нуждаются в приемлемой производительности своих устройств.Вашим пользователям не нужно, чтобы вы потребляли весь этот процессор и оперативную память.Это означает, что ваши пользователи должны дать вам одну звездную оценку на Маркете за то, что вы невнимательны к тому, что нужно им , думая только о том, что нужно вам , как будто вы важнее, чем ониare.

Как минимум, сделайте это настраиваемым, чтобы пользователь фактически мог контролировать, заслуживает ли ваше приложение того, что вы ищете, а не диктовать им условия.

...