来自服务的android小部件更新 - 内存泄漏?

时间:2010-12-10 22:22:25

标签: android service timer widget

我有一个Service,我想让它每秒更新主屏幕上的小部件。因此,服务会监听每秒TimeController发送的OnTimerEvent。 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 个答案:

答案 0 :(得分:4)

  

我有一个服务,我希望它每秒更新主屏幕上的小部件。

请不要那样做。应用程序窗口小部件机制专为更新频率更低的内容而设计 - 例如,每半小时更新一次。如果你这样做,你将把用户的电池敲打成粘贴,并从他们的前台应用程序窃取CPU时间(例如,削减他们正在玩的游戏的帧速率)。

一旦您将更新频率降至合理的水平,请不要提供服务,其唯一的使命是追踪时间。请改用AlarmManager

  

那么如何在没有如此大量内存泄漏的情况下更新视图呢?

根据定义,如果它被垃圾收集,它不是泄漏。分配垃圾收集的内存时发生泄漏。因此,你不会泄露记忆。

  

哦,我忘记了:是的,我知道不推荐每秒更新小部件,但我真的需要至少每10秒更新一次。

您的用户确实需要从他们的设备中获得可接受的性能。您的用户不需要消耗所有这些CPU和RAM。这意味着您的用户需要在市场上为您提供一星级评级,因为他们不会考虑他们需要什么,只考虑需要什么,就好像您更重要比他们好。

至少要使其成为可配置的,因此用户实际上可以控制您的应用是否值得您所寻求的内容,而不是您向他们口述条款。