Android Basics: Async Task
May 20, 2020
Tags: Android, Android Basics, Github API, AsyncTask, Github Repository App,
AsyncTask is used to run tasks that might take some time on other thread so that the UI thread is not blocked and the UI keeps running smoothly while the task keeps running in the background.
AsyncTask is now deprecated, but I do believe it is going to be supported for a while. The alternatives are to use the standard java.util.concurrent or Kotlin concurrency utilities instead.
Before we get started with AsyncTask I want to add an OnClickListener
to the Search Button so that we can respond to clicks. You can find more here. Right now are are going to create a toast which is going to display our search term.
// In onCreate after we did our findViewById's.
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do something when the search button is clicked.
Context context = v.getContext();
Toast.makeText(context, mSearchQueryEditText.getText(), Toast.LENGTH_LONG).show();
// TODO: Query Github API
}
});
This is what it looks like
Creating an AsyncTask
So AsyncTask has 4 steps:
- onPreExecute() : invoked on the UI thread
- doInBackground(Params…): invoked on the background threads
- onProgressUpdate(Progress …): invoked on the UI thread
- onPostExecute(Result): invoked on the UI thread
As the names suggest onPreExecute
is invoked before doInBackground
, anything you want to do before running the task goes here. Then we have doInBackground
, this is where the task runs, we could also call publishProgress
which sends progress updates to onProgressUpdate
, it can be used to update things like progress bars or percentages. onPostExecute
is where we get the result of our task.
So lets build a simple AsyncTask for our app.
// This would be outside onCreate since we are creating a new class
private class QueryGithubAPITask extends AsyncTask<URL, Void, String>{
@Override
protected String doInBackground(URL... urls) {
try {
return NetworkUtils.getResponseFromHttpUrl(urls[0]);
}catch (IOException e){
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mSearchResultTextView.setText(s);
}
}
private class QueryGithubAPITask extends AsyncTask<URL, Void, String>
We specify the type of parameters the three functions(in the order doInBackground
, onProgressUpdate
, onPostExecute
) take at the very top, since we are not using onProgressUpdate
we put Void
.
@Override
protected String doInBackground(URL... urls) {
try {
return NetworkUtils.getResponseFromHttpUrl(urls[0]);
}catch (IOException e){
e.printStackTrace();
}
return null;
}
Here all we are doing is to get a url and then pass it into a function that we previously created in our network utils in the doInBackground
functions and then using the result we get and pass that on to onPostExecute
.
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mSearchResultTextView.setText(s);
}
}
Since doInBackground
returns a String onPostExecute
accepts a String as its argument. We use the result from the doInBackground, in our case a String and set it as text in one of the TextViews.
Using the AsyncTask
Now that we have our AsyncTask setup we want to use it when we press the search button. This is pretty straight forward, we change the search buttons onClickListener to check if we have an empty search bar and if we have a search term we search it by executing our AsyncTask.
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String githubSearchQuery = mSearchQueryEditText.getText().toString();
// Making sure our search bar(EditText) isn't empty
if(githubSearchQuery.equals("")){
Context context = v.getContext();
Toast.makeText(context, "Please enter a search term.", Toast.LENGTH_SHORT).show();
}else{
// Building the url with the search term
URL url = NetworkUtils.buildUrl(githubSearchQuery);
// Calling our AsyncTask
new QueryGithubAPITask().execute(url);
}
}
});
Lets try and search something to see if our app works
A good exercise would be to try and add a progress bar so that when we are fetching JSON we show the progress bar and when we are done fetching we hide the progress bar and show our edit text.
So the app works, but all we see is a wall of text with lots of JSON. A good idea would be to parse the JSON and display only the names of repos. Let’s explore how we could do that in the next post.
You can find the code here.