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.
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:
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.