- 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.
- 數據科學實戰手冊(R+Python)
- Web應用系統開發實踐(C#)
- 一步一步學Spring Boot 2:微服務項目實戰
- 機器學習系統:設計和實現
- Java應用開發與實踐
- VMware vSphere 6.7虛擬化架構實戰指南
- bbPress Complete
- Learning Unity 2D Game Development by Example
- Python之光:Python編程入門與實戰
- Building Wireless Sensor Networks Using Arduino
- Geospatial Development By Example with Python
- Raspberry Pi Robotic Blueprints
- MINECRAFT編程:使用Python語言玩轉我的世界
- Visual FoxPro 6.0程序設計
- C指針原理揭秘:基于底層實現機制