AsyncTask goes through four steps when executed:
1. onPreExecute() is invoked on the UI thread before the task is executed
2. doInBackground(Params...) is invoked on the background thread immediately after onPreExecute() finishes
3. onProgressUpdate(Progress...) runs on the UI thread after publishProgress(Progress...) is invoked
4. onPostExecute(Result) runs on the UI thread after the background computation has finished