SQlite operations completes half if user remove the application - android

As suggested by developers, The sqlite operations must be performed on the Background thread. But in some cases, if the sqlite operations are being performed on Background thread And during that, the user remove the application from recent task.
This causes app to be gone in an undesired state. Sometimes cause a crash next time when I open my app.
If I perform sqlite operation on UI thread, everything goes fine.
My app has lot of sqlite operations to be performed at lot of times. How should I deal with this.

Related

Can asynchronous LiveData/Room queries lead to race conditions?

Consider a simple activity containing two fragments:
RecordListFragment: A RecyclerView bound to LiveData<Record> via a #Query and a button which calls a #Delete query for a Record
RecordEditFragment: Several widgets to change the record and a save button which calls a #Insert or #Update query for a Record
The documentation for RoomDatabase.Builder#allowMainThreadQueries states:
Room ensures that Database is never accessed on the main thread because it may lock the main thread and trigger an ANR. If you need to access the database from the main thread, you should always use async alternatives or manually move the call to a background thread.
Every tutorial/blog/example I found states the same, you should not block the UI thread with database work. My instinct disagrees: There's nothing more I want when inserting or deleting data from a database than having an easy way to block the user from interfering.
If all database access happens on a worker thread one possible order of events that comes to mind is:
The user deletes Record a on the RecordListFragment
The user manages to enter the RecordEditFragment for Record a
The background thread executes the deletion
The user tries to save/update the non-existent Record a
Boom
Another scenario is:
The user updates an existing Record a from the RecordEditFragment, transitioning to RecordListFragment
Before the list has a chance to update the user reenters the RecordEditFragment for Record a
The RecordEditFragment opens with old data
The background thread executes the save
Boom
These are classic race conditions when working asychronously and I cannot imagine that this is actually best practice on Android but I cannot find any documentation that states otherwise. Are these scenarios actually possible or does Android prevent stuff like this from happening? Why not just block the UI for a simple task like inserting a record to not have any possibility of a race condition?
You can block the user from interfering with tasks without "blocking the UI".
You said:
There's nothing more I want when inserting or deleting data from a database than having an easy way to block the user from interfering
You can definitely change the UI so that it won't let the user do something while you have background processes or whatever you want running. That is not what "blocking the UI" is. Blocking the UI means blocking the UI thread from being able to operate.
Modern Android development, including built in functionality with Kotlin Coroutines, in some ways prevents you from blocking the UI thread by not even compiling until you fix your code. But it's possible that you could be supporting older versions of Android or else not using those language features, so it is still up to you to not write code that will run slowly on the UI thread. This makes it so that your UI seems to be responsive even if the things going on in the other threads might be taking a while.
So, if you need to write to RoomDB or run a network request, that should go on another thread like the IO thread.
See https://developer.android.com/guide/components/processes-and-threads
for more information regarding Android processes and threads (specifically read the sectino about Threads), or for more specific information about how Kotlin Coroutines help check out https://developer.android.com/kotlin/coroutines-adv
Especially, note the following quotes from the Android developer link above:
When the thread is blocked, no events can be dispatched, including drawing events ...
... the Android UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
So go ahead and fire off that background work on another thread, and change your UI to show that it's doing something until that other thread completes. Then you have prevented the user from interfering and you've also made the app work in a way that doesn't appear broken.

Should Content resolver insert happen in a background thread?

I am unsure if there is a need to do processing in a background thread for content resolver insert functionality. I did it as a part of UI thread and the application runs file. But need to know if it is right calling inserts directly on ui thread.
I'd recommend against it. Database writes are slow, and should be performed off the UI thread where possible. It may not be a problem for you now, but you may find that as your database grows or the nature of your application changes and you start writing more data, your UI thread will start to lag behind.
You may also find that this kind of operation in its current form might not run so smoothly on lower-end devices.
In addition to these issues, if you plan to share your database between multiple threads, concurrent writes can and will be blocked by the database lock to assure data integrity; this in turn may leave your UI thread hanging.
So, although it may not be a problem right now, you can save yourself a lot of time in the future by implementing and working with a design pattern that does ensure your transactions occur off the UI thread.
Whatever you do, make sure you give yourself a pat on the back for making this consideration in the first place!

Why is the UI thread blocked when work is done on a separate thread?

In my app, I have a ViewPager with +/- 10 pages. When the app is first opened, all the pages are instantiated and immediately begin to load data to display. Each page (which are fragments) creates an AsyncTask to query a database and populate itself with the appropriate data. Here's the problem: even though the work is being done on separate threads, the UI stops updating during the database queries (which are done sequentially, and take 1-3 seconds total). This happens both on my Nexus 5 and a crappy old Samsung phone, so I know the problem is not that the hardware just can't keep up.
So ultimately, I'm wondering why the UI thread is blocked by work done on a background thread. My understanding of threading was that doing work on one would not block the other for an extended period of time. If my understanding is wrong, please explain how. Thanks in advance.
I don't think code is required here, but if it is, let me know and I will post the relevant portions.
It stops animating immediately after the first database query begins and starts animating again immediately after the last database query completes
It is possible, then, you are not doing the work on a background thread that you think you are. You may be doing the work on the main application thread.
Traceview can help you identify what you are doing on the various threads, and StrictMode can help you with obvious problems (disk I/O and network I/O on the main application thread).
In this case, you may be getting caught by how you are doing your work:
Each page (which are fragments) creates an AsyncTask to query a database and populate itself with the appropriate data.
If you are doing your query in doInBackground() but are not touching the resulting Cursor also in doInBackground(), the query actually wasn't done yet. The Cursor is a SQLiteCursor, and it lazy-executes the query when the data is first used. This is another one of those "really cool ideas that just plain suck in how we do things nowadays". A workaround is to call getCount() on the Cursor while you are in doInBackground(), to ensure that the query actually is executed on the background thread.

Is it ok to perform DB operation on UI thread?

I am using a database to persist the state of a search form. I am using the onPause method to persist the data and the onResume method to restore it. My opinion is that restoring and persisting state should be a blocking operation so I plan to perform the database operations on the UI thread. I know this is generally discouraged but the operations should be quick and I think if they were done asynchronously they could lead to inconsistent UI behaviour.
Any advice
Even if you want the application to not accept user input while the slow operations are being performed, you still don't want to do them in the UI thread. This is for two reasons:
Fully non-responsive UIs are a big nono. If you need to lock your user away from interacting with the program, you need to assure him that something is actually going on - anything else is likely to be interpreted as your application being buggy. Use dialogs, toasts and/or progressbars while the application is working, as appropriate.
Android will offer users the option of force-closing applications that it thinks are hanging. You don't want this to happen during what is normal behaviour for your application is taking place.
Even if you want it to be a blocking operation, you have to show the user that some thing is happening. Because when the UI thread is blocked, the screen will not respond to any touch operation of the user. Sp, you can have an indefinite progress bar in your onPause() and onResume() methods till the persistence and restoration is done. And obviously you will have to do it in a separate thread. Because if the UI thread is not responding for sometime, android can give the Application Not Working error.

When should I do certain SQLite operations on another thread(not the main thread)?

My Android application includes an SQLite database with an SQLiteOpenHelper class to help manage it. During application use, the user may perform some operations such as adding/deleting/updating etc on the database.
At some points the size of the operation will be known, like this:
user clicks button to save item
the SQLiteDatabase performs a single insert query
user continues using app
At other areas of the app, the operation may be large, like inserting 10+ items into the database all at once.
Questions:
should I thread simple operations like inserting/updating/deleting/viewing 1 item?
will it take longer to insert 1 item into a table which contains many items(like 30+) than it would take to insert into a table with no items?
if i don't need to thread such simple operations, at what point do you suggest i start threading them?
when i say thread i mean using a thread that is not the main UI thread.
edit: I realize that small operations do not take much time and i could very well get away with doing them on the main thread. I am just concerned that it would be bad practice to be executing them on the main thread and would like clarification!
General rule for everything: If it's fast enough, do it on the main thread. If not, use a worker thread.
Unless you have a ridiculously huge database, a single operation almost never warrants a separate thread. Databases in general are designed to scale well, but of course a very big database (10,000+ rows?) will be a bit slower than a small one. 30 rows, however, is nothing.
I would start threading stuff if you have a lot of operations going on, like a bunch of queries, or complicated queries that span several tables.
As with everything - profile your app, and if it's too slow, optimize. Don't write an awesome synchronized super-duper multi-core-ready database handler if none of your queries takes longer than 2ms.
Always measure before you optimize!
Make sure that DB operations you do affect user experience and than start looking for a solution.
If database stuff gets slow, then use AsyncTask, which was designed to perform tasks in the background, and then update the GUI on EDT.
There is absoulutely not reason to use a thread here. Just return the cursor, extract the information from the cursor and return it to the main activity.
Specifically speaking a thread is something ideally that is going to repeat until something happens or it times out. Since the database you are using i'm assuming is on the phone, it would take practically zero time to access it.
Also another thing you can do is create a Utility class to assist with your activity to database interaction. It would be what your activity calls to interact with the database. Specifically the flow of control would be like this:
Activity -> Utility -> Database
Its between the activity and the database to keep them isolated from each other and make it much easier to access whatever it needs since it doesn't have to go directly to the database itself.

Categories

Resources