首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 圖片加載進度顯示:AsyncTask + ProgressDialog 實現

     編輯:程式設計綜合問答

場景

同步加載網絡圖片阻塞 UI,需異步下載並顯示進度對話框,完成後顯示圖片。

方案:AsyncTask 封裝下載邏輯


public class ImageLoadActivity extends AppCompatActivity {
    private ImageView imageView;
    private ProgressDialog progressDialog;
    private static final String IMAGE_URL = "https://example.com/large-image.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_load);
        imageView = findViewById(R.id.imageView);
        
        // 初始化 ProgressDialog
        progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("加載中");
        progressDialog.setMessage("正在下載圖片...");
        progressDialog.setCancelable(false);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); // 或 STYLE_HORIZONTAL 需進度更新
        
        // 啟動異步任務
        new DownloadImageTask().execute(IMAGE_URL);
    }

    private class DownloadImageTask extends AsyncTask {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog.show(); // 顯示對話框
        }

        @Override
        protected Bitmap doInBackground(String... urls) {
            String url = urls[0];
            try {
                URL imageUrl = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(10000);
                conn.connect();
                
                int contentLength = conn.getContentLength();
                InputStream input = conn.getInputStream();
                
                // 可選:下載到 ByteArrayOutputStream 並按塊發布進度 (STYLE_HORIZONTAL)
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                byte[] buffer = new byte[4096];
                int len, total = 0;
                while ((len = input.read(buffer)) != -1) {
                    output.write(buffer, 0, len);
                    total += len;
                    if (contentLength > 0) {
                        int progress = (int) (total * 100 / contentLength);
                        publishProgress(progress); // 觸發 onProgressUpdate
                    }
                }
                input.close();
                
                byte[] data = output.toByteArray();
                return BitmapFactory.decodeByteArray(data, 0, data.length);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            progressDialog.setProgress(values[0]); // 更新水平進度條
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            progressDialog.dismiss(); // 隱藏對話框
            if (bitmap != null) {
                imageView.setImageBitmap(bitmap);
            } else {
                Toast.makeText(ImageLoadActivity.this, "圖片加載失敗", Toast.LENGTH_SHORT).show();
                imageView.setImageResource(R.drawable.ic_error);
            }
        }
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }
}

關鍵點解析

方法執行線程用途
onPreExecute()UI 線程任務啟動前:顯示 ProgressDialog、初始化 UI
doInBackground()後台線程耗時操作:網絡下載、解碼、發布進度
onProgressUpdate()UI 線程更新進度條、提示文本
onPostExecute()UI 線程任務完成:隱藏對話框、設置圖片、錯誤處理

現代替代方案 (棄用 AsyncTask 後)

AsyncTask 在 API 30 棄用,新項目請使用:

  • Kotlin Coroutines + Flow:viewModelScope.launch { ... }
  • RxJava:Observable.fromCallable(...).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
  • Jetpack Lifecycle + LiveData:配合 CoroutineLiveData。
  • 圖片加載庫:Glide/Picasso/Coil 內建進度監聽、緩存、佔位圖,**完全替代手寫下載邏輯**。

Glide 進度監聽示例


Glide.with(this)
     .load(url)
     .listener(new RequestListener() {
         @Override
         public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
             progressDialog.dismiss(); return false;
         }
         @Override
         public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
             progressDialog.dismiss(); return false;
         }
     })
     .into(imageView);
progressDialog.show();

總結

教學/維舊項目可用 AsyncTask + ProgressDialog 實現基本流程。**生產新項目請直接接入 Glide/Coil 等庫**,獲得緩存、生命周期感知、錯誤重試、動畫轉場等企業級能力,避免重複造輪子。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved