I had personally struggled with this topic, and I have seen many other Android beginners to have problem with understanding AsyncTask. In this tutorial, I will explain the AsyncTask in detail with example of it.
In Android, Main Thread should be available to handle events from different UI elements such as views and components. When programmer uses main thread to perform the task for more than 5 seconds, the activity will try to manage the resources and try to do the task. But if problem occurs getting memory and resources, then it issues an Application Not Responding (ANR) . ActivityManager and WindowManager are two classes responsible for monitoring the responsiveness of the app, and it issues the ANR if heavy task has been performing on the main thread. This is when the AsyncTask comes into play.
WHY USE AsyncTask?
AsyncTask provides many automated functionality which makes our life easier. In fact, AsyncTask is one of the most easiest way to implement separate thread without dealing with complex methods like threads. Though it offers basic level of threading, it shouldn't be used for the tasks for more than few seconds. Approximately 3 4 seconds only. When you use AsyncTask, you don't need to worry about following things,
Three Parameters is necessary for AyncTask. This will be given when creating a subclass. In below skeleton example, look at this line.
Now, look at the image below that will explain you how this four methods works together to accomplish a task.
AsyncTask provides many automated functionality which makes our life easier. In fact, AsyncTask is one of the most easiest way to implement separate thread without dealing with complex methods like threads. Though it offers basic level of threading, it shouldn't be used for the tasks for more than few seconds. Approximately 3 4 seconds only. When you use AsyncTask, you don't need to worry about following things,
- Create your background thread.
- Terminate that background thread at an appropriate.
- Organize your methods to handle code that needs to be processed on UI thread. For instance, updating a progress bar in response to downloaded bytes.
- Manage message queues or handlers to background thread.
How to use AsyncTask?
This can be divided in following simple steps :
- Create a subclass of AsyncTask.
- Override methods that you need to perform task. You must implement doInBackground() method, because this is where thread is created to perform long running task on separate thread.
- Supply your results to give an update. For instance, when doInbackground() downloads a simple file, you might want to send the progress of it on UI, so user will know that certain task has completed by this percent.
- After implementing, execute the Subclass created by passing necessary parameters to perform the task in background.
Now, I am pretty sure, this doesn't make it easier to understand. I might have given you more questions than it answers, but be patient, i will give detailed explanation.
AsyncTask has four methods to do the task :
- onPreExecute() :This defines what needs to performed and initialized before you perform the task. I guess name itself explains pretty well.
- doInBackground() :This is most important method as it is were the new thread is going to be created to perform the task. You must implement atleast this method to perform the task.
- onProgressUpdate() :While you perform the task, you might want to send the information about it on User Interface to let the user know.
- onPostExecute() :This defines what you want to do with the result of task. What you want to do with received data or after the completion of task in doInBackground() method. For instance, you might want to update the TextView with received text.
Three Parameters is necessary for AyncTask. This will be given when creating a subclass. In below skeleton example, look at this line.
public class MyTaskActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // This starts the AsyncTask // Doesn't need to be in onCreate() new MyTaskOnThread().execute("Whats the URL ajay? "); // execute(params) ; //we are passing thread.execute("string") in this example. // so params in the asyncTask will be String. } // Here is the AsyncTask class: // // AsyncTask
. // Params – the type (Object/primitive) you pass to the AsyncTask from .execute() //We passed execute("my string") = so It is going to be String. // Progress – the type that gets passed to onProgressUpdate() // it means what kind of result/update will be received? In this example, // we are giving update in lets say percentage, so its Integer // Result – the type returns from doInBackground() // What would be the outcome after AyncTask is done? In this example, we are going to receive the String, // So result parameter would be String. // Any of them can be String, Integer, Void, etc. private class MyTaskOnThread extends AsyncTask { // Runs in UI before background thread is called @Override protected void onPreExecute() { super.onPreExecute(); // Do something like display a progress bar or setting up variables necessary } // This is run in a background thread @Override protected String doInBackground(String... params) { // get the string from params, which is an array String myString = params[0]; // Do something that takes a long time, for example: for (int i = 0; i <= 100; i++) { // Do things // Call this to update your progress publishProgress(i); } return "Result is sent to onPostExecute : Url is apprajapati9.blogspot.ca"; } // This is called from background thread but runs in UI @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); // Do things like update the progress bar } // This runs in UI when background thread finishes @Override protected void onPostExecute(String result) { super.onPostExecute(result); // Do things like hide the progress bar or change a TextView } } }
Now, look at the image below that will explain you how this four methods works together to accomplish a task.
Rules of Using AsyncTask
- The AsyncTask class must be loaded on the UI thread. ie. Main Thread
- The task instance must be created on the UI thread.
- exectue(Params..) must be invoked on the UI thread.
- You cannot call onPreExecute() , doInbackground(), onPostExectue and onProgressUpdate() methods manually, you must define a class extending AsyncTask.
- The task can be executed only once. For instance, if you download a file by clicking on button, you cannot create another thread of AyncTask inside that.
Tutorial
In this example, You will be creating following app, where you can add elements using AsyncTask, and as it adds the elements in ListView, you will be able to see the Progress bar with it.
First of all , Create a project in android studio, with Blank Activity.
Now, we need to create UI first. In your project, find the MainActivity's layout file. In this project, i have content_main.xml. Add following code in your content_main.xml , to create the UI.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="asynctask.apprajapati.com.asynctasktutorial.MainActivity"
tools:showIn="@layout/activity_main">
<ProgressBar
android:id="@+id/progress"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:maxHeight="20dip"
android:minHeight="20dip" />
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progress"
android:layout_centerHorizontal="true"
android:text="Start Async" />
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_below="@+id/start"
android:layout_marginTop="60dp" />
</RelativeLayout>
The above code will create our following screen
Now, we have our UI elements are ready to use.
Add following code in your MainActivity.java file.
public class MainActivity extends AppCompatActivity {
ListView listView;
//Elements that going to fill in ListVIEW
String[] arrayList = {"1","2","3","4","5","6","7","8","9","10","DONE","Toast", };
// String[] myarray;
ProgressBar progressBar;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Progressbar
progressBar = (ProgressBar) findViewById(R.id.progress);
button = (Button) findViewById(R.id.start);
//At start we don't want our Progress bar Visible
progressBar.setVisibility(View.INVISIBLE);
progressBar.setMax(12);
progressBar.setProgress(0);
// myarray = getResources().getStringArray(R.array.counting);
//Initializing the ListView
listView = (ListView) findViewById(R.id.listView);
Setting up adapter
listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, new ArrayList() ));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MyTask().execute();
}
});
//nothing is passed to execute! So Params = Void
}
// AsyncTask
// Params, the type of the parameters sent to the task upon execution.
// Progress, the type of the progress units published during the background computation.
// Result, the type of the result of the background computation.
class MyTask extends AsyncTask{
//during execute() nothing is passed, so Void as Params
//String
private ArrayAdapter adapter;
private int count = 0 ;
@Override
protected void onPreExecute() {
//Everytime item is added, you need to publish
adapter = (ArrayAdapter) listView.getAdapter();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected Void doInBackground(Void... params) {
for(String item : arrayList){
publishProgress(item); //Every String element is passed! So Progress = String
//puasing the thread so you can see Progressbar and elements being added in app.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null; //returning null so, RESULT = Void
}
@Override
protected void onProgressUpdate(String... values) {
adapter.add(values[0]);
count++;
progressBar.setProgress(count);
}
@Override
protected void onPostExecute(Void aVoid) {
//After AsyncTask is done, Disappear the Progressbar
progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(MainActivity.this, "AsyncTask DONE", Toast.LENGTH_LONG).show();
}
}
}
In the above example, We are passing array of string inside ListView. This is the most simplest and basic example. This is all you need, and now run the app now, and check it out.
Challenge : If you guys have understood this properly, please comment below, what do you need to do in order to change the Progress parameter to Integer instead of String. Currently in this example, we have String as Progress parameter. Comment the change you need to make, so we can pass Integer as Progress parameter.
I hope this has given you detailed explanation of AsyncTask works! I will add another example anytime soon.
If you guys have any suggestion or problem understanding , leave a comment.
Happy Coding guys!
1 Comments
Good explanation
ReplyDelete