- Asynchronous Android Programming(Second Edition)
- Helder Vasconcelos
- 652字
- 2021-07-14 10:43:15
Providing deterministic progress feedback
Knowing that something is happening is a great relief to our users, but they might be getting impatient and wondering how much longer they need to wait. Let's show them how we're getting on by adding a progress bar to our dialog.
Remember that we aren't allowed to update the user interface directly from doInBackground()
, because we aren't on the main thread. How, then, can we tell the main thread to make these updates for us?
AsyncTask
comes with a handy callback method for this, whose signature we saw at the beginning of the chapter:
protected void onProgressUpdate(Progress... values)
We can override onProgressUpdate()
to update the user interface from the main thread, but when does it get called and where does it get its Progress... values
from? The glue between doInBackground()
and onProgressUpdate()
is another of AsyncTask's methods:
protected final void publishProgress(Progress... values)
To update the user interface with our progress, we simply publish progress updates from the background thread by invoking publishProgress()
from within doInBackground()
. Each time we call publishProgress()
, the main thread will be scheduled to invoke onProgressUpdate()
for us with these progress values.
The modifications to our running example to show a deterministic progress bar are quite simple. Since we have already defined the DownloadImageTask
Progress type as Integer, now, we must change the setting progress values in the range 0 (setProgress
) to 100 (setMax
) and set the style and the bounds of the progress bar. We can do that with the following additions to onPreExecute()
:
@Override protected void onPreExecute() { ... // Sets the progress bar style progress.setProgressStyle( ProgressDialog.STYLE_HORIZONTAL); progress.setIndeterminate(false); progress.setProgress(0); progress.setMax(100); progress.setCancelable(false); progress.show(); }
We also need to implement the onProgressUpdate
callback to update the progress bar from the main thread:
@Override protected void onProgressUpdate(Integer... values) { progress.setProgress(values[0]); }
The final modification is to calculate the progress at each iteration of the for
loop, and invoke publishProgress()
so that the main thread knows to call back onProgressUpdate()
:
private Bitmap downloadBitmap(URL url) { InputStream is = null; ... // Before Download starts publishProgress(0); downloadedBytes = 0; // Creates a Connection to the image URL HttpURLConnection conn = (HttpURLConnection) url. openConnection(); ... // Retrieves the image total length totalBytes = conn.getContentLength(); ... BufferedInputStream bif = new BufferedInputStream(is) { int progress = 0; public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { // The number of bytes read in each stream read int readBytes = super.read(buffer, byteOffset, byteCount); .. // Actual number of bytes read from the file downloadedBytes += readBytes; // Percent of work done int percent = (int)((downloadedBytes * 100f) / totalBytes); // Publish the progress to the main thread if (percent > progress) { publishProgress(percent); progress = percent; } ... }
It is important to understand that invoking publishProgress()
does not directly invoke the main thread, but adds a task to the main thread's queue, which will be processed at some time in the near future by the main thread.
Notice that we're being careful to publish progress only when the percentage actually changes, avoiding any unnecessary overhead:
Note
Is important to know that every time you invoke publishProgress()
on the background thread, in downloadBitmat()
, a new Handler message is sent automatically internally to push the progress to the main thread.

Figure 3.4: Deterministic Progress Dialog showing the task progress
As can be seen in Figure 3.4, the deterministic dialog created in onPreExecute()
is updated continuously in doInBackground()
with the current progress of the task. The progress is calculated as a ratio, as in the following division:
The delay between publishing the progress and seeing the user interface update will be extremely short for this example and for any application that doesn't have too much UI work to process. The progress bar will update smoothly following the golden rule of not blocking the main thread for any of our code, since we only dispatch a progress update when the percentage changes.
- Android應用程序開發與典型案例
- 工程軟件開發技術基礎
- 密碼學原理與Java實現
- Drupal 8 Blueprints
- Instant 960 Grid System
- 從Excel到Python:用Python輕松處理Excel數據(第2版)
- PhoneGap:Beginner's Guide(Third Edition)
- R語言:邁向大數據之路(加強版)
- .NET 4.0面向對象編程漫談:應用篇
- Mastering ASP.NET Core 2.0
- Building E-Commerce Solutions with WooCommerce(Second Edition)
- Visual C++實用教程
- Activiti權威指南
- Java EE 7 First Look
- Java編程兵書