I have a ListActivity which launches another Activity based on the list selection. This second Activity needs to load data by parsing from the xml file and as such there is a noticeable delay between when the user clicks on an item and when the Activity displays.
Between this process user have to be indicated with progress bar at the bottom of the screen with out freezing the activity.
You should take a look at the AsyncTask class which enables you to do background processing and publish processing status without halting the main Activity.
Whenever you use some GUI library, there will be this concept: You have one thread that is for GUI events, in Java-Swing called the "Event Dispatching Thread" EDT, in Android as well as SWT, it's called the UI-Thread. This thread is responsible for all GUI events and manipulation. Time consuming actions must be done on another thread so the UI doesn't block/freezes.
(I think it is important to understand this basic concept of UI development, rather than just use AsyncTask and think that this is something Android specific)
EDIT
painless threading in Android
Threads in Swing
EDT Wikipedia
Related
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.
in my app, i'm uploading some files that can take up to several minutes. i'm thinking of a way to notify the user about activity going on passively by adding a progress bar in my custom title bar. what i want to do is have every activity, each which uses the custom titles, appear with the progress bar until the thread finishes and does a callback which would make invisible the progress bar. can something like this be accomplished?
what seems to make this impossible is that if the user is in an activity with the view loaded, the thread finishing callback would have to manipulate the loaded view resources to disable the progess bar which doesn't seem feasible. are there any suggestions to accomplish this or alternative solutions in keeping a global and passive indication of something going in the background?
You can use a service to achieve this. Services
Basically how it would work, is you bind to the service in each activity when you create the activity. You use this service to start your upload method.
When you bind to the service you pass a handler, which is then used to update your UI in that specific activity. The service will never directly affect the UI (it will be running on a separate thread) instead the handler passes a message back to the UI thread with data in a Bundle, such as upload progress, or a bool to say it's finished.
I have the following structure:
in UIActivity1:
MyMyProgressDialogFragment progressDialog = MyMyProgressDialogFragment.newInstance();
progressDialog.show(getFragmentManager(),"dialog");
getFragmentManager().executePendingTransactions();
..do some heavy work and send messages to progressDialog
The DialogFragment gets created and the ProgressBar in this fragment starts spinning.
But when I now start the heavy work in the activity which created the dialog fragment the progress bar within the fragment stops.
When reading through the fragment doc I understand that a fragment has its own activity - same as the Ui Activity1. And afaik each activity runs in a separate thread.
So why does the progressbar in the dialog fragment stop when the UIActivity1 starts with its heavy work?
Shouldn't they be independant?
ps when I run the heavy work outside the UIActivity in a different task again, the progress bar keeps spinning without problems.
Where is my mistake in understanding here?
Thanks!
Its not clear from the information you have shared, however looks like you are doing all your heavy execution in your UI Thread. That is the activity's main thread. Whether the activity you spin off with your fragment is meant to do just this work is irrelevant, the UI thread has to be used only to update the UI elements and generally avoid tasks that take longer than 100 - 200 ms. This is as per android Non-Responsive Application documentation. This is probably the problem, any long standing or long executing tasks have to be done in a background thread.
Take a look at this example of using the progressbar in Android.
I have a comment activity that loads a Thread and sends some data to a server; the activity is immediately finished once the submit button is pressed.
The user is then free to do other things in my application.
When the server responds an AlertDialog is shown.
The problem is that since the initial context has been destroyed, my application crashes.
I tried getApplicationContext() but still get an exception.
Put your network stuff in a Service, then show a status bar notification instead of a dialog.
Take a look at AsyncTask
From JavaDocs:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.