Here is the case:
In my app, I have service which is used for communication with other special device. In the middle of this communictation I need to query database in my app to get data neccesary to proceed communicating with 2nd device. Here I am using rawQuery with 2 parameters. Query is a not too complicated cause I am actually quering view in database. As a result I should get back around 50 rows and 25 columns.
The thing is that if I just call this query from service (same thread) it blocks my UI for like 6 seconds. There is animation signaling long operation which got stuck.
On the other side, if I call exactly same query in doInBackground of AsyncTask (to move it from UI thread) my animation flows without troubles but for same amount of data query now need 25 seconds til 1 minute depending on which phone I am testing.. (almost 1min take on new Motorola with Intel cpu)
I measure times and where is so much time lost (cause queries and databases are exactly the same on both phones) and all this time is wasted on first access to cursor. In my case c.moveToFirst() ..
My question is more Android oriented not SQL, cause in my app I integrate already complete, filled with data, database
Any idea, anybody?
Edit: I try different solutions for issue I have and here is interesting thing I came to: When I use another thread with Runnable which has query, time is reduced back to few seconds (exactly like everything is executed in UI thread)
Thread t = new Thread(RunnableWhichHoldQuery); //then I just start thread t.
Still not sure why AsyncTask is behaving like it does.. Now I am just curious for explanation cause I would like to understand better what is going on.. thanks to everybody with ideas..
Related
I'm wondering what the possible drawbacks are to running my queries on the main thread. At the moment I am loading data from a database using Room and am using this data to generate graphs for the user.
I have already tried putting my queries into separate threads using a runnable, but I am having issues with the application attempting to use data which has not yet been loaded due to the separate thread not finishing it's operation in time. I understand that I could implement some sort of listener or notification, but even then, the user will have to wait an undetermined amount of time before they may view the content because the data for the graphs that they are wanting to view never loads before the button that loads them is clicked.
I have done quite a bit of research and found that it is unadvisable to put the queries on the main thread because it could possibly hang up the thread for a long time and give a poor user experience. So, assuming that I will never exceed 1400 data members, should I worry about this? Are there any caveats that I have not been informed of?
Edit: I am testing the device on a Samsung SM-J106B which is running Android 6.0.1 and I have not noticed any impact on performance even when loading the max of 1400 data members.
DB queries could take long enough that they would cause the UI to skip frames causing a bad visual experience or worse trigger an app not responding exception.
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.
I am able to fetch contacts using this code https://stackoverflow.com/a/1780818/992774 , it works perfectly fine and returns all the emails and phone numbers.But my problem is that when I have 10,000 of contacts it takes about 3-4 minutes and for that time it blocks my UI and looks like my app got halted. I have seen many apps like groupme which shows contacts without taking any time.Can anyone suggest how to reduce the time while fetching contact thousand of contacts or how can I create custom cursor adapter?
Can you do the loading in a separate thread, either using a Handler or an AsyncTask, for an example please refer to this tutorial http://www.vogella.de/articles/AndroidPerformance/article.html
This will leave your UI thread to be free to do UI stuff and you should be able to see your contacts get populated one by one on your screen.
use CursorLoader to get your cursor. It runs asynchronously, so you won't hang your UI thread while you're retrieving data.
It still may take some time. Is it worth stepping back for a second and asking if you need to look at 10,000 contacts? Seems to me that it's nearly impossible to search through them on the screen.
My program involves interaction with SQLite in a fairly regular basis, and in the beginning of the app, I call a query
mDatabase.rawQuery("SELECT key,
indice as _id
FROM Dictionary",null);
Strangely the app stalls on executing this line. This does not happen if I am debugging the application, but when I run the app, the control goes from this line and never returns. I have checked this by putting logcat before and after this line.
I have not been able to comprehend this behavior. Can someone help?
P.S. The table Dictionary has over 2000-3000 records.
EDIT:
I have tried calling this from both UI & separate threads. Either ways, the execution stops at this call (for that thread). So when I call it from another thread, though there is no ANR, the call still fails and holds the thread indefinitely.
EDIT2:
This issue does not happen every time I run the application but 5 out of 10 times. And apparently happens more on weaker phones.
Take care of below points.
Make call to query in separate thread other than UI thread.
Cursor at max can hold upto 1MB of data. So query for minimum amount of data.
You should take this off the UI thread. Looks like a heavy call. Anything which takes longer than 5 seconds and stalls the UI thread will trigger an ANR.
Yes piyushnp and abhinav are right. AsyncTask or Thread are better option for getting the details. Show progressbar when doing background processing. And when you get query results display it in activity or do whatver processing you want on query results.
This example simulates your problem. AsyncTask basic Example : AsyncTask
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.