我有一个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消息。那么如何在没有如此大量内存泄漏的情况下更新视图呢?
谢谢!
答案 0 :(得分:4)
我有一个服务,我希望它每秒更新主屏幕上的小部件。
请不要那样做。应用程序窗口小部件机制专为更新频率更低的内容而设计 - 例如,每半小时更新一次。如果你这样做,你将把用户的电池敲打成粘贴,并从他们的前台应用程序窃取CPU时间(例如,削减他们正在玩的游戏的帧速率)。
一旦您将更新频率降至合理的水平,请不要提供服务,其唯一的使命是追踪时间。请改用AlarmManager
。
那么如何在没有如此大量内存泄漏的情况下更新视图呢?
根据定义,如果它被垃圾收集,它不是泄漏。分配不垃圾收集的内存时发生泄漏。因此,你不会泄露记忆。
哦,我忘记了:是的,我知道不推荐每秒更新小部件,但我真的需要至少每10秒更新一次。
您的用户确实需要从他们的设备中获得可接受的性能。您的用户不需要消耗所有这些CPU和RAM。这意味着您的用户需要在市场上为您提供一星级评级,因为他们不会考虑他们需要什么,只考虑您需要什么,就好像您更重要比他们好。
至少要使其成为可配置的,因此用户实际上可以控制您的应用是否值得您所寻求的内容,而不是您向他们口述条款。