Say I have main activity that contains a list (never mind if it is a ListView or RecyclerView). Each time the activity is created it has in its onResume method a query for data from parse. The thing is the parse query I use calls findInBackground method so my list in main activity is always zero since by the the time the activity is constructed the query hasn't finish yet. when I use find (and not find in background) I see in android studio logcat a sentence like the follwoing : "to many operation on main thread".
What do u think I should do?
Thank u in advance
Expansive operations like this should be done on a seperate thread in the background, so the main (animation) thread will not be blocked, causing your app to lag. The findInBackground() method will do the same as find(), but on a different thread 'in the background'. When the job is done, it will call the FindCallback and pass the result so you can update your list.
Untill this is done you could show a intermediate ProgressBar in front of your empty list to indicate that the data is loading.
Related
I finished reading the Cursors and AsyncTasks chapter in Head First Android Development, and I'm still not sure when to use AsyncTask and when not to when performing database operations.
Suppose I'm at an activity which, when it ends, writes to sqlite database and sends the user back to the main activity (using finish()), which displays a list of data that is fetched from the database.
The list of data obviously has to update instantly, just as the user enters back to MainActivity. Does this mean I shouldn't use AsyncTask in this situation? What other choices do I have here? I don't want to let the user see the changed list of data after MainActivity is already visible.
A simpler scenario: The user clicks a button that should display database information in a TextView. Should this be done in a separate thread? I'm not sure, because the TextView must be updated immediately.
The best practice for read & write data in the database is: do it in a separate thread. Because it can take a lot of time, if the amount of data is fairly large or the query itself is too complicated, do it in the main thread can cause ANR.
If you want to display data changes immediately, you can do it as following:
place a method in the ui activity to change ui according to the parameters
triggered update ui through invoke the method above in the async callback
as for your last example, u can update the content of the textview immediately in the onPostExecute method of AsyncTask class
if you are not using AsyncTask u can just update ui in other thread through one of the ways below:
Activity$runOnUiThread(Runnable runnable)
new Handler(Looper.MainLooper()).post(Runnable runnable) //create handler for main thread, and post runnable to execute in main thread
send message to message queue, then handle the message and update ui in the main thread's handler
Normally you should do database queries on a separate thread, but if you're sure the database is relatively small(light) you could perform it on the main thread. but its always best practice to do potential long running tasks on a different thread.
I have ListView which shows, through an Adapter, the data from a global ArrayList. If I want to add an element to this ArrayList the proper approach is to do that in the main (UI) thread and immediately call Adapter.notifyDataSetChanged() afterwards, in order to avoid an "IllegalStateException: The content of the adapter has changed but ListView did not receive a notification". However the ArrayList is changed in a secondary thread, executed by a Service which is not bound to the Activity all the time, and thus does not always have a reference to the Adapter in order to post these operations in the main thread queue. So when (I suppose) the main thread runs into the changed list, the exception ensues.
I see two ways of circumventing this:
Make the Adapter global so I can reference it any time I want.
Clone the list and make the Adapter backed by the clone. Thus when the original list is changed the clone will remain untouched until the moment the main thread needs to exhibit the changes (e.g. on Activity.onResume()), at which I update the clone based on the original and call notifyDataSetChanged().
The drawbacks of the second approach seem to be the apparently unnecessary redundancy and the memory overhead (although the list is not big, at maximum some 500 objects of 12 fields each). I tend to choose the first one, but which one do you find best? If there is a third approach, please let me know.
As you've not shown your code, I don't know if this might help, but have you considered using a CountDownLatch? in the manual page comes a perfect example on blocking the execution of a thread until the Latch is released. You could simply declare an instance in your main Activity and pass a reference to the Service and other involved parts.
As your service is unbound, you might use a BroadcastReceiver to pass the instance to the service, or even using a Semaphore instead, as this last is serializable and thus able to be put as an extra to an Intent (you would need to bind the Service in that case, though).
I have question regarding my previous ListView activity.
I have my ListView which is continue updating using socket connection, now when I click on any of the list row i can go to my next screen now when i come back to my previous ListView screen my ListView is start updating again but i want to keep updating my ListView in a background when i am on my nextscreen.
Something like i want to keep my previous screen alive when i am on my nextscreen.
Sounds to me like your the code you are using to load the data for your ListView is tied to your Activity.
For instance you have an AsyncTask or Thread in your Activity that cointains your ListView and you use it to download data, or do whatever is needed to get the data to populate the list. I also assume you start it in one of the Activity lifecycle methods e.g. onCreate().
If that is the case then you should consider seperating the code used for getting the data for the list from your activity code.
One way to do this is to use a Service which will be able to run independantly of the rest of your application and do all the heavy lifting involed with fetching the data for your list. You can communicate with the service from anywhere in your application. The Service can save the data to a database. Then all you have to do in your Activity is query the database and populate the adapter to get the latest data without much delay.
You can read more about services here:
http://developer.android.com/reference/android/app/Service.html
You could (and probably should) do what Paul suggested or you could change to way you switch your screens by using Fragments or a ViewFlipper. This way you still run your AsyncTask or Thread while doing something else on a different page.
I know it sounds crazy that someone is using runOnUiThread inside AsyncTask. Somehow, it is working for me but I wanna know if it is an acceptable and robust approach or not. Here is the scenario:
I have an app in which after successful login, user is rendered to next screen. In this new screen, 3 different methods are loading different types of data from a web server. These methods are:
getMembersForList() : It loads the list of community members and shows it in a listview.
getProfileData() : It loads the profile of logged in user and shows his name , image etc on the screen.
getNotificationCounts : It loads the count of new notifications for the user.
I applied 3 different approaches for it :
(1) Calling all 3 methods simply in onCreate i.e. no exclusive thread is being used for any of the methods . In this case , the transition from login screen to this screen becomes very slow and black screen shows up for some time before this activity shows up.
(2) Calling getMembersForList() on UI thread and the other 2 methods on exclusive threads. In this case transition becomes fast and list shows up quickly but Notification counts and username etc. don't show up because WrongThreadException occurs saying that this thread can't touch other thread's views (TextViews for username, notification count etc. which are declared globally) . The same thing happens when I start these threads from an AsyncTask as well.
(3) Calling getMembersForList() on UI thread and then starting an AsyncTask in which the other 2 methods are being called in "runOnUiThread" inside doInBackground() method. This solves both the above issues. Now the screen transition is faster and the WrongThread exception is also not occuring.
So far the approach-(3) is working good for me but I am not sure if this is the right way to do it because runOnUiThread and AsyncTask are 2 completely opposite things. Can anyone please clear my doubts about this scenario. Thanx in advance.
Yes, use-cases like this are a big reason why the runOnUiThread() method exists in the first place. The idea is you allow your background thread(s)/AsyncTask instance(s) to run your lengthy operations in the background, and then provide a simple hook that they can use to update the interface when they have the result (or at arbitrary intervals, as different pieces of the result become available).
As long as that's what you're doing, then your usage is fine. What you want to avoid doing is performing a lengthy operation on the main thread, either directly or indirectly by passing in some lengthy operation from a background thread.
Of course you don't have to do it that way if you don't want to. You could use postExecute() instead. Or you could store the result somewhere and then use any sort of message-passing API to notify the main thread that the result is ready, and so on.
I would advice to run all the 3 calls in the asyncTask, and update the UI in the postExecute() of the AsyncTask after the background taks is complete, postExecute runs on UIthread so you need not call anything explicit to run them on UIthread.
My Android application is running very slow and lagging much. I have PHP API on my server and my application requests data through HTTP.
Though, the problem is that sometimes I should wait for few seconds before I can see the result. I have all calculations done in the main thread in onCreate (parsing XML, adding controls) and downloading data from HTTP server in AsyncTask.
How to optimize my program to make it faster? I want it to load activity first and only then, in background, download and parse data. How is it possible? Sorry for newbieship.
what did you mean by lagging ? Will you elaborate more on the issue.
One suggestion that remove parsing XML from OnCreate and move it to AsysnTask. The reason for this is as you are doing time consuming operation in UI Main thread which will impact the activity to be shown.
Create thread to perform HTTP related operations and parse the response on the same thread and while doing the parsing operation show dialog.
Dismiss the dialog when parsing got completed and then show the activity which you want to display.
In the doInBackground() method in AsyncTask add the data parsing and create the data objects then in onPostExecute update the ui elements.
The reason to do something like that is for the application to be responsive in all this time and just make small jobs on the ui thread so as not to freeze.
You can instatiate your views to a default state an add a progress somewhere on top to indicate that the activity is currently loading. For example you can create an empty ListView or a Button that cannot be selected and when the parsing is done then you should set the adapter to the list and make the button back to selectable again.
All this things can be implemented according to what you want the user to be able to do in the time of his waiting.