How to implement single step undo for SQLite DB changes? - android

I am trying to adapt my application from a confirmation model to an undo model. For those of you who don't know, this is where you can delete something with one click but if it was a mistake you can undo it just as easily, as opposed to interrupting the user every time he/she wants to do something to ask the annoying "Are you sure you want to...?" question via dialog.
My app is backed by the Android SQLite DB and I want to be able to undo a limited set of delete and update operations. Also, I only need to be able to undo one sequential change and the information does not have to stick arround for very long.
Everything I read on undo/redo says to use a command model to store the data. My question is how can I store the database changes in a lightweight restorable way?

The idea of the command pattern is, that every command knows how it can be undone. For instance, an AddPersonCommand would add a new record to the Persons-table in your database. To undo this command, you would have to delete that person again.
Depending on the type of application and the complexity of the database, you can just write the changes to the database like you normally would. You always keep the last X command objects (X being the number of actions that can be undone), and if necessary, invoke their undo-method.

You can also use RestorableSQLiteDatabase library which is a wrapper around android's SQLiteDatabase and automatically generates restoring SQL queries to undo changes using a tag name.

Related

Start the API call as soon as record inserted in Sqlite database in android

I have a requirement, if a record inserted in local DB(Sqlite) as soon as possible app triggers API call to send offline record to server. I don't want to use Timer and Alarm service because those will run continuously in background even there is no offline records in local DB. Any other alternative solutions?
Note: Target SDK level is Andorid 8 version.
As I understood your task (in general) - is how to invoke some function (some sendNewRecord() for instance) when new row(s) were inserted in some Sqlite table.
I suppose there are 3 alternative ways to implement such a task in Sqlite:
To invoke your function at the same place in code where you put your insert-new-data code. I think that's the most obvious and the simplest choice. I hope in your app there is only one place where you do it (Repository pattern or its analogue).
To put some observer(callback function) to your table and process changes in table. That more complicated task, and as far as I know you'll get this callback after every change in your table and it would be another task to identify what rows in your table were changed. Using modern Room framework and LiveData as a query result, you can observe changes in the table in more strait-forward way, but then nevertheless you have to detect inserted rows.
To use some scheduling mechanism for syncing (Executor, Timer and so on). You've wrote that it's not your case.
I would recommend you to choose first way. At least I don't see its disadvantages.

Mobile devices offline sync with webservice

Im am developing a webservice for an App that I am writing. I want to make the App offline accessible.
I made that webservice so that if you request JSON from the webservice you can give a date:
/color/colors/date/2014-03-01T12:00/
If you don't give the date you will get everything that is inside the database and that is active. If you give the date you will only get everything that is updated after that date.
Now my problem is that if I remove something from the webservice of from the App then it will not be synced and the other devices will never know that it is removed.
I could work with a field where I say that a record is removed but then I need to keep every record and I can't delete any record.
Is there a better way to do the syncing? Or what is the best way?
I think there is no possible way to detect the deleted entry's change, unless you send the information that the entry is deleted. The best practise you set a field in the table with integer type, then you can set this value on updates. You don't have to set it only 1 or 0, you can use bigger numbers (for example I used 30 on that entries, that I deleted on 20th march , on this day was a big code logic change. after that i knew when the status integer is 30, then i deleted this row after that date.) It may be a silly example, but you can implement your own logic.
It depends on how important it is to update the rest of the devices when a change is made.
If it is critical, then it would be worth implementing push notifications or something similar to each device to let them know about the updated situation. Otherwise, you would simply have the other devices poll the server to check for changes on their own accord, and the frequency or the trigger of this poll would depend again on how critical it was that they get an update. Maybes they only need updating when they visit a certain activity, so in that case you would only poll when you reach the onResume() event of that activity
Update
If you don't need to keep a history of the deleted record, then why can't you just delete it, and then when the rest of the devices update, you clear all and download a fresh set? If that is too intensive, you would NEED to have a reference to the id, which you could do in a table or use a special value in the field (like null, 0 or -1) to mark it. Otherwise there would be no way to reference it

Android Database Insert At The Beginning

I want to insert required data for my application at the beginning and I will use these data. And I want to insert once, and there must be no duplicate. Therefore, in "onCreate", I'm doing like that : if the row count of table(such as student etc) is 0, I'm inserting students. I don't think it's the best way to do this. Therefore I want to learn if there is a better way.
If you want your database populated at install time and never any other time, your only reasonable option is to package your pre-populated database with your APK as a built-in resource. This has the advantage of simplifying your app.
Alternately, if you implement the SQLiteOpenHelper for your database, anything you insert during SQLiteOpenHelper.onCreate(SQLiteDatabase) will only ever be inserted either on the first run of you app or when someone clears all your app's data (which is more or less putting you back to a fresh install anyway). The SQLiteOpenHelper superclass knows whether or not to run the creation code when you call one of the getWritableDatabase() or getReadOnlyDatabase() methods to get your database reference.
It is worth noting that Android doesn't really let you run an installer the way desktop software does. If you need to do any setup work, you need to be able to detect and remember when your app has been run before.

How to determine which row in contacts database has been updated

I am writing a backup application and need to know which records in the contacts database have been updated, so that I can backup only those records. I have looked at the documentation and it seems that there is a "DIRTY" constant field in ContactsContract.RawContacts class, which is supposed to be set to "1", for the rows that are updated. But it is not clear to me as to when will this field get cleared to "0". Can someone provide me example code on how to use this? Can this field be used to determine if a contact has been added or updated?
If this is not the correct way to achieve what I am trying to do can anyone suggest me another way. I am also aware that I can use the RegisterContentObserver() call to identify whenever there is a change in the Contacts database but this will require my application to be running always in the background, which is way too expensive and I do not want to do that.
If there is anyway to extract the timestamp when the various contacts have been added or updated that would be perfect too, but I cannot find how to do that.
Any help is very much appreciated.
I have looked at the documentation and it seems that there is a "DIRTY" constant field in ContactsContract.RawContacts class, which is supposed to be set to "1", for the rows that are updated. But it is not clear to me as to when will this field get cleared to "0".
In my experience, whenever there is a 'dirty' indicator of some sort, it is the responsibility of the backup/sync app to reset it once the data has been successfully committed during a backup/sync operation.
This can cause problems, however, when more than one application is used - the first one run at any time after data has been updated will reset the flag and the next one run wont find anything to backup/sync.
In this case if you require that a user is able to use a 'sync' app (for example) but you also want to have a 'backup' operation then registering a ContentObserver would serve a better purpose and there's no reason why this should be 'expensive' on resources if implemented correctly.
EDIT: Although there is no 'timestamp' there is a 'VERSION' field which is updated (which is when 'DIRTY' is set). If you backup this field, you could simply leave the 'DIRTY' flag set and compare current VERSION in the contacts DB with your most recent backup.

Implementing a robust persistent undo/redo feature

I'm writing a bitmap editor where I use the Command Pattern to represent actions that will transform the document. I keep all the commands executed so far in a list and, to implement undo, I restore the document to its initial state and then replay all but the last command.
I would like my undo/redo system to have the following feature: When the user closes the editor and returns, the document, including the available undo and redo commands, should be restored to the state it was in when the user left.
I'm implementing this for Android where your application can be given very little notice before it will be cleared from memory if e.g. the user gets a phone call. Also, some of my commands are e.g. a list of all the x,y co-ord the user painted on so these might take a few moments to save to disk.
My current idea is as follows:
When a new action is performed, the command object is added to a list S for commands that need to be saved to disk.
A background thread is used that will continually take commands from list S and save them to disk. The postfix of the filenames used will be numbered in sequence. For example, if the user filled the screen then drew 2 circles, the command files might be called FillCommand1.cmd, DrawCircleCommand2.cmd, DrawCircleCommand3.cmd.
Periodically, we save a "checkpoint" command whose purpose is to store the full document state so that, even if one of the .cmd files is corrupted, we can restore a recent version of the document.
When the user exits the app, the background thread attempts to finish up saving all the commands it can (but it might get killed).
On startup, we look for the most recent .cmd file that represents a checkpoint that we can load successfully. All the .cmd files we can load after this (i.e. some files might be corrupt) go in the redo command list, all the .cmd files we can load between the first checkpoint loaded and the oldest checkpoint we can load go in the undo list.
I want the undo limit to be about 20 or 30 commands back so I need extra logic for discarding commands, deleting .cmd files and I've got to worry about multi-threading behaviour. This system seems pretty complex and will need a lot of testing to make sure it doesn't go wrong.
Is there anything in Java or Android than can help make this easier? Am I reinventing the wheel anywhere? Maybe a database would be better?
Rather than reverting to the original then performing all actions, consider making Commands reversible. That way, if you ever decide to increase the size of your undo history, you won't be introducing the potential for lag while undoing. Alternatively, as Jared Updike notes, your application may benefit from caching render results in the near past and future.
I think you're overcomplicating things with your filesystem-based solution. If you want to maintain a backup of the entire history of current working document, you should just keep an unbuffered log open in append mode, and log actions to it. The log should be associated with the particular instance of the application and file being edited, so you don't have to worry about another thread stepping on your toes. Loading from that log should be very similar to loading from an ordinary save file. Just discarding the last-read action whenever you encounter an undo action.
Well, your code is probably imperative in nature, where the state of the application is modified in place by the user's actions. This is probably fast and straightforward. Undo is basically time-travel and if you clobber old states by modifying state in place you will have to store either recipes to recompute it in reverse, or a history that can recompute it forwards.
Like you said, you can store the actions and the initial state and play them forward (stopping at the new point in history the user selects) but that means undoing one action can cause n actions to replay. One approach is to store saved state copies in the history list so you can immediately jump to a given state. To avoid using too much RAM/storage you if your system is clever it can detect the nearest (non-null) saved state in the history and recompute those few stpes forward (assuming you have all the actions you need -- this assumes actions are small and state is large(r)) until the correct state is reached. In this manner you can start eliminating old saved states (delete or set to null) (drop the state based on a cost function inversely linear to how far back in time the state is), making undo fast for the recent past, and memory/storage efficient for ancient history. I've had success with this method.

Categories

Resources