I am developing an application which is having four tabs. In each tabs I have implemented each separate functions. I would like to implement threads for each tabs to make the program more efficient. Can anybody suggest the way to implement threads in tabbed activity?
You could put the running function either using the java Thread class or the doInBackground method by extending an AsyncTask class.
Ref: http://developer.android.com/reference/android/os/AsyncTask.html
I am not seeing the advantage to having each tab run in its own thread. The advantage to threading in Android would be to do time consuming work in the background, which would prevent the UI from locking up. What is it that each tab will be doing?
You can have threads to do background work in each tabbed Activity, but if you are planning on updating the UI, it must be done in the 'primary', or UI, thread.
On the android documentation there is a great article about "painless threading" you might wanna try from there. I would recommend not to take an approach for each tab instead try to keep in background those task that might block your UI thread (like downloading or parsing).
Here is a small snipped that might help you
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.adapter = new PersonAdapter(this, R.layout.main_item, new ArrayList<Person>());
setListAdapter(this.adapter);
ListView listView=(ListView)findViewById(R.id.section);
sectionAdapter=new SectionAdapter(this,R.layout.section_item,sections);
listView.setAdapter(sectionAdapter);
//execute the filling section task in background
progressDialog = ProgressDialog.show(MainFeedActivity.this,
"Please wait...", "Retrieving data ...", true);
new SectionTask().execute();
new FeedTask().execute();
}
private class SectionTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
//ProcessInformation Here Background Thread you can do downloading and parsing
}
#Override
public void onPostExecute(Void result){
//Update your UI here [UI Thread]
}
Be careful though there is a AsyncTask limit
Related
I am a beginner to Android and I have some confusions regarding Android UI Thread. Now, I know that no thread apart from the one that created the UI can modify it.
Great.
Here is the Activity from my first Android app which slightly confuses me.
public class NasaDailyImage extends Activity{
public ProgressDialog modalDialog = null;
//------------------------------------------------------------------------------
#Override
protected void onCreate(Bundle savedInstanceState){
//Instantiate progress dialog, skipping details.
Button b = //get reference to button
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
modalDialog.show(); // show modal
Toast.makeText(getApplicationContext(), "Getting feeds", 500).show();
new AsyncRetriever().execute(new IotdHandler()); // Get the feeds !!
}
});
}
//------------------------------------------------------------------------------
public synchronized void resetDisplay(boolean parseErrorOccured,
boolean imageErrorOccured,
IotdHandler newFeeds){
if(parseErrorOccured || imageErrorOccured){
// make a Toast
// do not update display
}else{
// make a Toast
// update display
// based on new feed
}
}
//------------------------------------------------------------------------------
class AsyncRetriever extends AsyncTask<IotdHandler,Void,IotdHandler>{
#Override
protected IotdHandler doInBackground(IotdHandler... arg0) {
IotdHandler handler = arg0[0];
handler.processFeed(); // get the RSS feed data !
return handler;
}
//------------------------------------------------------------------------------
#Override
protected void onPostExecute(IotdHandler fromInBackground){
resetDisplay( // call to update the display
fromInBackground.errorOccured,
fromInBackground.imageError,
fromInBackground);
}
//------------------------------------------------------------------------------
}
1. onCreate is on the UI thread so I can do whatever I want but onClick is not. Why can I make a ProgressDialog and a Toast in that method? Why no error there?
2. The AsyncTask is subclass of the the NasaDailyImage. This means it can access all the methods of NasaDailyImage including resetDisplay() which updates the display. resetDisplay() is called in the onPostExecute which runs on a different thread from UI. So, why can I update the display there and yet get no errors ?
onClick() is indeed on the UI thread. Most of what happens in an Activity happens on the UI thread.
onPostExecte() (and its counterpart onPreExecute()) runs on the UI thread as well. The AsyncTask.onPostExecte() documentation clearly states this. AsyncTask was deliberately designed such that developers could update the UI before and after they do background work.
In general, your code will be running on the UI thread unless you explicitly tell it otherwise. Once you create AsyncTasks, Runnables, or Threads, you need to ensure you understand where your code is executing. In an Activity, it is typically safe to assume you are on the UI thread.
You are extending AsyncTask class , where async task class is calling its sequential method automatically. First onPreExecute then doBackground and finally onPost. If you want to change any ui change you can use onProgressUpdate method.
To use your activity class simple call activityclass.this.resetDisplay(). Because inner class scope sometimes failed to integrate except global varible.
Thanks
In one activity of my app I make a bunch of edit text fields dynamically and then set them with some text from sharedpreferences. I realise that this is a bit much for the main thread to handle which is why there is some lagging of the app when it loads. I am quite new to the concept of threads so I was wondering what the best way was to put the loading of the strings from sharedpreferences into another thread and then just display a loading bar(or similar) in the meantime(in the main thread I guess). Please explain in great detail because threads are new to me.
Also if there are any tutorials on this that point me the the right direction they would also be useful. Thanks in advance.
AsyncTask is what you need.
Create a class that extends AsyncTask
Do your heavy work in doInBackground()
Example:
Class Example extends AsyncTask{
#Override
protected void doInBackground(Object... args){
//do ur stuff
}
#Override
protected void onPostExecute(Object arg){
//do what you wanna do after doInBackground
}
}
Call your task by new Example().execute();
Whilst only the main thread can make changes to the UI, you can you the AsyncTask class to do all the other work on another thread and then push things to the main thread as they are ready to be put on the UI.
YOu can have something like this: Just to guide you
final ProgressDialog pd = ProgressDialog.show(context, "Title", "Loading");
new Thread(new Runnable()
{
#Override
public void run()
{
//get data from shared preferences
runOnUiThread(new Runnable()
{
#Override
public void run()
{
pd.dismiss();
//set that text to your dynamic textview
}
});
}
}).start();
I have a Main activity with a few methods.
GetTopics: calls REST API and returns JSON results
BindTopics: displays the results from GetTopics on the screen
There are a few others with similar functionality, but I'm sure I can fit the solution to these across all methods.
Question: What is the proper way to run these in separate threads? Should both of them be in the same thread? Should I call BindTopics once GetTopics is complete?
Either way, doesn't the UI get built prior to the async threads are completed? If so, how do I update the UI?
Any help is appreciated.
The answer to all your questions is AsyncTask
I would load it in a progress dialog with an AsyncTask. You will need to declare the handler to update controls in the UI thread.
Example:
private Handler handler = new Handler();
final ProgressDialog pd = new ProgressDialog(this);
pd.setTitle("Getting topics..");
pd.setMessage("Please while topics are retrieved");
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setIndeterminate(true);
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
GetTopics();
return null;
}
#Override
protected void onPreExecute() {
pd.show();
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
BindTopics();
pd.dismiss();
handler.post(new Runnable() {
public void run() {
// update UI
// remove loading view
// load details of topics
}
});
super.onPostExecute(result);
}
}.execute();
You want to create your UI (with some sort of loading screen), then start an AsyncTask to download the data and display it.
There is a basic blog post about AsyncTasks here: http://android-developers.blogspot.co.uk/2009/05/painless-threading.html
In the AsyncTasks doInBackground method you would call GetTopics. Then in the onPostExecute method you would call BindTopics and display the data. In the onPostExecute method you can check to see if the data downloaded properly before attempting to display it.
The main use of threads for me were when my app had to download large amount of data from ftp server. But while downloading I wanted that the user still can use my app. If I had written the download code in main thread, the user could not use the app and all buttons would not work. The main idea of thread is to divide time of CPU usage for each thread.
If you wish more then one task to be preformed simultaneously you have to use Threads.
I'm displaying some data by using SQLite. When I click on one button data come from database. It takes some time. At that time the screen is black. At that time I want to display the rotating spinner before the data dispay. Any ideas?
Android provides a ProgressDialog for accomplishing what you want.
First i would like to suggest to have a look at AsyncTask page, so that you will come to know about the AsyncTask exactly.
Now, Implement AsyncTask as given below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new performBackgroundTask().execute();
}
private class performBackgroundTask extends AsyncTask <Void, Void, Void>
{
private ProgressDialog Dialog = new ProgressDialog(main.this);
protected void onPreExecute()
{
Dialog.setMessage(getString("Please wait..."));
Dialog.show();
}
protected void onPostExecute(Void unused)
{
Dialog.dismiss();
// displaying all the fetched data
}
#Override
protected Void doInBackground(Void... params)
{
// implement long-running task here i.e. select query/fetch data from table
// fetch data from SQLite table/database
return null;
}
}
Enjoy !!!
You should not execute long running tasks in UI thread as this blocks the UI redraw and makes app look unresponsive.
Use AsyncTask to execute long running tasks in background, while still updating the screen.
You can look at the standard music picker as one example of how to do this:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java
In addition to the whole "queries must be done off the main UI thread," this shows an indeterminant progress while first loading its data, fading to the list once the data is available. The function to start the query is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#581
And to do the switch is here:
https://android.googlesource.com/platform/packages/apps/Music/+/master/src/com/android/music/MusicPicker.java#569
The layout has the list view put in a frame layout with another container holding the progress indicator and label. The visibility of these is changed to control whether the list or progress indicator are shown:
https://android.googlesource.com/platform/packages/apps/Music/+/master/res/layout/music_picker.xml
I've got an Android activity which grabs an RSS feed from a URL, and uses the SAX parser to stick each item from the XML into an array. This all works fine but, as expected, takes a bit of time, so I want to use AsyncActivity to do it in the background. My code is as follows:
class AddTask extends AsyncTask<Void, Item, Void> {
protected void onPreExecute() {
pDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Retrieving data ...", true);
}
protected Void doInBackground(Void... unused) {
items = parser.getItems();
for (Item it : items) {
publishProgress(it);
}
return(null);
}
protected void onProgressUpdate(Item... item) {
adapter.add(item[0]);
}
protected void onPostExecute(Void unused) {
pDialog.dismiss();
}
}
Which I call in onCreate() with
new AddTask().execute();
The line items = parser.getItems() works fine - items being the arraylist containing each item from the XML. The problem I'm facing is that on starting the activity, the ProgressDialog which i create in onPreExecute() isn't displayed until after the doInBackground() method has finished. i.e. I get a black screen, a long pause, then a completely populated list with the items in. Why is this happening? Why isn't the UI drawing, the ProgressDialog showing, the parser getting the items and incrementally adding them to the list, then the ProgressDialog dismissing?
I suspect something is blocking your UI thread after you execute the task. For example, I have seen folks do things like this:
MyTask myTask = new MyTask();
TaskParams params = new TaskParams();
myTask.execute(params);
myTask.get(5000, TimeUnit.MILLISECONDS);
The get invocation here is going to block the UI thread (which presumably is spinning off the task here...) which will prevent any UI related stuff in your task's onPreExecute() method until the task actually completes. Whoops! Hope this helps.
This works for me
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(viewContacts.this);
dialog.setMessage(getString(R.string.please_wait_while_loading));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
It is because you used AsyncTask.get() that blocks the UI thread "Waits if necessary for the computation to complete, and then retrieves its result.".
The right way to do it is to pass Activity instance to your AsyncTask by constructor, and finish whatever you want to do in AsyncTask.onPostExecution().
If you subclass the AsyncTask in your actual Activity, you can use the onPostExecute method to assign the result of the background work to a member of your calling class.
The result is passed as a parameter in this method, if specified as the third generic type.
This way, your UI Thread won't be blocked as mentioned above. You have to take care of any subsequent usage of the result outside the subclass though, as the background thread could still be running and your member wouldn't have the new value.