在 Android 開發中,常需從網路下載圖片並顯示縮略圖以節省記憶體。本方法示範如何透過 HttpURLConnection 下載位元組資料,再利用 BitmapFactory.Options.inSampleSize 進行次採樣解碼,有效防止 OutOfMemoryError。
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class ImageUtil {
/**
* 從 URL 載入圖片並生成縮略圖
* @param urlString 圖片網址
* @param targetSize 期望縮略圖最大邊長(像素)
* @return 縮略圖 Bitmap,失敗回傳 null
*/
public static Bitmap loadThumbnail(String urlString, int targetSize) {
if (urlString == null || urlString.isEmpty()) return null;
ByteArrayOutputStream outputStream = null;
BufferedInputStream bis = null;
InputStream is = null;
try {
URL url = new URL(urlString);
is = url.openStream();
bis = new BufferedInputStream(is, 4096);
outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
outputStream.flush();
byte[] imageData = outputStream.toByteArray();
// 第一次解碼:僅取得圖片尺寸
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
// 計算 inSampleSize
int height = options.outHeight;
int sampleSize = (int) (height / (float) targetSize);
if (sampleSize <= 0) sampleSize = 1;
else if (sampleSize > 3) sampleSize = 3; // 限制最大縮放倍數
options.inSampleSize = sampleSize;
options.inJustDecodeBounds = false;
// 第二次解碼:取得縮略圖
return BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (OutOfMemoryError e) {
System.gc();
return null;
} finally {
closeQuietly(outputStream);
closeQuietly(bis);
closeQuietly(is);
}
}
private static void closeQuietly(java.io.Closeable c) {
if (c != null) try { c.close(); } catch (IOException ignored) {}
}
}
// 在背景執行緒中呼叫(如 AsyncTask、RxJava、Coroutines)
String imageUrl = "https://example.com/large_photo.jpg";
Bitmap thumb = ImageUtil.loadThumbnail(imageUrl, 200); // 200px 縮略圖
if (thumb != null) {
imageView.setImageBitmap(thumb);
}
OutOfMemoryError 並呼叫 System.gc() 嘗試回收。finally 區塊確保所有串流正確關閉,避免洩漏。實務專案建議使用成熟圖片載入庫(Glide、Picasso、Coil),它們內建快取、生命週期感知、佔位圖等功能,寫法更簡潔:
Glide.with(context).load(url).override(200).into(imageView);