Reputation: 12312
I have a Service
and I want it to update a widget on the homescreen each second. Therfore the Service listenes to an OnTimerEvent which is send by an TimeController
each second. The TimeController
is a singleton holding a handler which runs 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);
}
};
// ...
}
This all works and the widget get's updated, but in Logcat I see:
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
And I don't like what I see... :-)
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);
}
}
}
If I comment out the remoteViews.setTextViewText(...)
the GC messages do not appear. So how can I update the view without having such a huge memory leaking?
Thanks!
Upvotes: 1
Views: 4121
Reputation: 1007624
I have a Service and I want it to update a widget on the homescreen each second.
Please do not do that. The app widget mechanism is designed for stuff that is updated much less frequently -- say, once every half-hour. You will hammer the user's battery into paste if you do this, and steal CPU time from their foreground app (e.g., cutting frame rate of the game they are playing).
Once you drop the update frequency to something reasonable, please do not have a service whose sole mission in life is to track time. Use AlarmManager
instead.
So how can I update the view without having such a huge memory leaking?
By definition, if it is being garbage-collected, it is not a leak. A leak occurs when you allocate memory that is not garbage-collected. Hence, you are not leaking memory.
Oh I forgot: Yes, I know that updates of widgets each second are not recommended, but I really need a update at least every 10 seconds.
Your users really need acceptable performance out of their devices. Your users do not need you consuming all this CPU and RAM. Which means your users need to give you one-star ratings on the Market for being inconsiderate of what they need, thinking only of what you need, as if you are more important than they are.
At minimum, make this be configurable, so the user actually gets to control whether or not your app deserves what you seek, rather than you dictating terms to them.
Upvotes: 4