It can also save CPU usage (and thus battery) by doing deferred updates to protect from “machine-gun” updates/saves on e.g. every keypress from the user.
Benefits:
- can save CPU cycles, battery, storage medium wear, bandwidth
- re-usable, encapsulated, separated from business logic
- LGPL license
How I use it in my app (ttps://play.google.com/store/apps/details?id=com.dayagendaplanner&hl=en) :
- Deferring/batching of saves to persistent store (SD card)
- Deferring/batching updates to registered future alarm notifications
- Deferring/batching of re-computations of times in the table. Although this is less sweet because AutoSaver works best if its use does not delay UI updates.
Here’s the code.
https://github.com/karol-depka/LibreLib/blob/master/LibreLibAndroid/src/com/karoldepka/librelib/android/AutoSaver.java :
package com.karoldepka.librelib.android;
import android.os.Handler;
/**
* Re-usable class for batched/delayed saves/updates.
* Save occurs: at most {@link #delayMs} milliseconds after modification is reported
* (which is also the moment of timer restart).
* After save, the timer stops.
* After a modification is reported, timer restarts.
* If the timer is already running, it will not start again (will run its course to the end),
* otherwise there would be a risk of never saving if the modifications were reported
* at certain big frequency.
*
* @author Karol Depka Pradzinski
* @license LGPL
*/
public abstract class AutoSaver {
public boolean saveTimerRunning = false;
public class RunnableSave implements Runnable {
@Override public void run() {
saveNowIfNeeded();
saveTimerRunning = false;
}
}
private final int delayMs;
private final Handler mHandler = new Handler();
private Runnable runnableSave = new RunnableSave();
public AutoSaver(int delayMs) {
this.delayMs = delayMs;
}
protected abstract void saveCustom();
public void documentModified() {
ensureSaveTimerRunning();
}
private void ensureSaveTimerRunning() {
if ( !saveTimerRunning ) {
mHandler.postDelayed(runnableSave, delayMs);
saveTimerRunning = true;
}
}
public void saveNowIfNeeded() {
// TODO: only save if modified
forceSaveNow();
}
/** Useful e.g. when shutting down the app*/
public void forceSaveNow() {
saveCustom();
stopSaveTimer();
}
private void stopSaveTimer() {
mHandler.removeCallbacks(runnableSave);
saveTimerRunning = false;
}
public void destroy() {
saveNowIfNeeded();
}
}
Example usage:
https://github.com/karol-depka/LibreLib/blob/master/LibreLibAndroidExamples/src/com/example/librelib/android/examples/AutoSaverExample.java :
package com.example.librelib.android.examples;
import com.karoldepka.librelib.android.AutoSaver;
public class AutoSaverExample {
package com.example.librelib.android.examples;
import com.karoldepka.librelib.android.AutoSaver;
public class AutoSaverExample {
private final AutoSaver autoSaver = new AutoSaver(2000) {
@Override public void saveCustom() {
// save/push/update somewhere
}
};
/** Called when the user modifies the data */
public void onModified() {
autoSaver.documentModified();
}
public void onForceSave() {
autoSaver.forceSaveNow();
}
public void onDestroy() {
autoSaver.destroy();
}
}

This work is licensed under a Creative Commons Attribution 3.0 Unported License.