AsyncTask is a helper class that makes performing a background task and updating the user interface (UI) painless. The class takes care of the communication between the background thread and the main UI thread. All you have to do is override some methods in the AsyncTask class to perform the UI update(s).
In this post, we’ll be looking at a simple app that uses AsyncTask to download some data from an URL while enabling and disabling a progress bar. I am going to assume you have a general idea of what an AsyncTask is. If that is not the case, I recommend that you check out my post about AsyncTask before proceeding.
The Sample App
The app performs a simple functionality. It takes in an URL and tries to fetch the data at that URL. When the background task is fetching the data, the progress bar will be active. When the task is complete or is not fetching any data the progress bar will be inactive. After fetching the data successfully, it will be shown in the text view.
Using the Four Steps of AsyncTask
The sample app utilizes the four steps of an AsyncTask to perform the download and update the UI. The four steps are onPreExecute, doInBackground, onProgressUpdate, and onPostExecute. In each of the step, the following occurs:
- onPreExecute: Enables the progress bar, which makes it visible to indicate downloading.
- doInBackground: Performs a fetch for the data at the URL and store the data.
- onProgressUpdate: Do nothing here since the progress bar is set to intermediate. It just keeps moving to indicate that the app is not frozen. This is where you would update the progress bar or other UI to reflect the percentage of the task complete if it is known in advance.
- onPostExecute: Dismisses the progress bar by making it invisible and sets the text view to show the downloaded content. Note: in the example image, I used an URL to a webpage so what gets shown is the HTML version of the webpage.
The Code
public class MainActivity extends AppCompatActivity { private ProgressBar progressBar; private TextView webpageContentTextView; private EditText urlEditText; public class WebPageDownloader extends AsyncTask<String, Void, String> { protected MainActivity mainActivity; public WebPageDownloader(MainActivity mainActivityRef) { mainActivity = mainActivityRef; } @Override protected String doInBackground(String... urls) { StringBuffer webPageContentStringBuffer = new StringBuffer(); if (urls.length <= 0) { return "Invalid URL"; } try { String url = urls[0]; URL webUrl = new URL(url); InputStream webPageDataStream = webUrl.openStream(); InputStreamReader webPageDataReader = new InputStreamReader(webPageDataStream); int maxBytesToRead = 1024; char[] buffer = new char[maxBytesToRead]; int bytesRead = webPageDataReader.read(buffer); while(bytesRead != -1) { webPageContentStringBuffer.append(buffer, 0, bytesRead); bytesRead = webPageDataReader.read(buffer); } return webPageContentStringBuffer.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return "Failed to get webpage content"; } @Override protected void onPreExecute() { super.onPreExecute(); if (mainActivity != null) { mainActivity.showProgressBar(); } } @Override protected void onProgressUpdate(Void... progress) { super.onProgressUpdate(); } @Override protected void onPostExecute(String webContent) { super.onPostExecute(webContent); if (mainActivity != null) { mainActivity.dismissProgressBar(); mainActivity.setWebPageContent(webContent); } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progressBar = findViewById(R.id.progressBar); webpageContentTextView = findViewById(R.id.webpageContentTextView); urlEditText = findViewById(R.id.urlEditText); } public void getWebPageContent(View view) { WebPageDownloader webPageDownloader = new WebPageDownloader(this); String url = urlEditText.getText().toString(); try { // note: don't use get() if you want your UI thread to keep running // 'get' will pause the UI thread until the task finishes executing webPageDownloader.execute(url); } catch (Exception e) { e.printStackTrace(); } } private void log(String message) { Log.d("[Web Page Downloader] ", message); } private void showProgressBar() { progressBar.setVisibility(View.VISIBLE); } private void dismissProgressBar() { progressBar.setVisibility(View.INVISIBLE); } private void setWebPageContent(String webPageContent) { webpageContentTextView.setText(webPageContent); } }
<android.support.constraint.ConstraintLayout 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" tools:context="bddevlabs.com.webpagedownloader.MainActivity"> <ScrollView android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:fillViewport="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/progressBar"> <TextView android:id="@+id/webpageContentTextView" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Web Page Content Shows Here..." /> </ScrollView> <EditText android:id="@+id/urlEditText" android:layout_width="306dp" android:layout_height="wrap_content" android:ems="10" android:hint="Enter URL" android:inputType="text" android:textColorLink="@android:color/darker_gray" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/goButton" android:layout_width="73dp" android:layout_height="44dp" android:text="Go" app:layout_constraintStart_toEndOf="@+id/urlEditText" app:layout_constraintTop_toTopOf="parent" android:onClick="getWebPageContent"/> <ProgressBar android:id="@+id/progressBar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:indeterminate="true" android:indeterminateTint="@android:color/holo_blue_light" android:visibility="invisible" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/urlEditText" tools:visibility="invisible" /> </android.support.constraint.ConstraintLayout>
Above is the code for the activity and the layout of that activity. The main activity is where the AsyncTask goes off and fetch the data from an URL. For the entire Android project of this sample app, you can visit the GitHub page.
I hope this post was helpful to you. If you found this post helpful, share it with others so they can benefit too.
To get in touch, you can follow me on Twitter, leave a comment, or send me an email at steven@brightdevelopers.com.