核心步骤
无论使用哪种方法,下载网络图片的基本逻辑都包含以下几个步骤:

- 获取网络权限:在
AndroidManifest.xml中声明网络访问权限。 - 发起网络请求:使用 HTTP 客户端(如
HttpURLConnection或第三方库)从指定 URL 获取图片的输入流。 - 读取数据:从输入流中读取图片的二进制数据。
- 处理数据:将读取到的数据转换为
Bitmap对象。 - 显示图片:在
ImageView中显示Bitmap。 - 处理线程:非常重要! 网络操作不能在主线程(UI线程)中进行,否则会导致应用卡顿甚至崩溃(
NetworkOnMainThreadException)。
使用 HttpURLConnection (原生方法)
这是 Android SDK 自带的方法,无需添加额外依赖,适合简单的下载任务。
添加网络权限
在 app/src/main/AndroidManifest.xml 文件中添加:
<uses-permission android:name="android.permission.INTERNET" />
创建下载工具类
为了代码的复用和清晰,我们创建一个 ImageDownloadUtil 类。
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImageDownloadUtil {
private static final String TAG = "ImageDownloadUtil";
/**
* 使用 AsyncTask 下载图片 (已过时,但能很好地理解原理)
* @param imageView 要显示图片的 ImageView
* @param urlString 图片的 URL
*/
public static void downloadImage(ImageView imageView, String urlString) {
new DownloadImageTask(imageView).execute(urlString);
}
private static class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private final ImageView imageView;
public DownloadImageTask(ImageView imageView) {
this.imageView = imageView;
}
@Override
protected Bitmap doInBackground(String... urls) {
String urlDisplay = urls[0];
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(urlDisplay).openStream();
// 使用 BitmapFactory 解析输入流
bitmap = BitmapFactory.decodeStream(inputStream);
} catch (IOException e) {
Log.e(TAG, "Error downloading image", e);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
在 Activity 或 Fragment 中使用
import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private ImageView mImageView;
private String imageUrl = "https://example.com/path/to/your/image.jpg"; // 替换成你的图片URL
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.imageView);
// 调用工具类下载图片
ImageDownloadUtil.downloadImage(mImageView, imageUrl);
}
}
activity_main.xml 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="300dp"
android:layout_height="300dp"
android:scaleType="centerCrop" />
</LinearLayout>
使用现代协程 (Kotlin - 推荐方式)
如果你使用 Kotlin,协程是处理异步任务的现代、简洁且强大的方式,它避免了回调地狱,代码可读性极高。
添加网络权限 (同上)
添加协程依赖
在 app/build.gradle.kts (或 app/build.gradle) 文件中添加:
// 在 dependencies 闭包中添加 implementation 'androidx.core:core-ktx:1.12.0' // 通常已包含 implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2' // 提供 lifecycleScope
使用协程下载图片
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Log
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.HttpURLConnection
import java.net.URL
class MainActivityKotlin : AppCompatActivity() {
private lateinit var imageView: ImageView
private val imageUrl = "https://example.com/path/to/your/image.jpg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
imageView = findViewById(R.id.imageView)
// 在 Activity 的 lifecycleScope 中启动一个协程
// 当 Activity 销毁时,协程会自动取消
lifecycleScope.launch {
val bitmap = downloadImage(imageUrl)
if (bitmap != null) {
imageView.setImageBitmap(bitmap)
}
}
}
private suspend fun downloadImage(urlString: String): Bitmap? = withContext(Dispatchers.IO) {
// withContext(Dispatchers.IO) 将这段代码切换到 IO 线程执行
var bitmap: Bitmap? = null
var connection: HttpURLConnection? = null
try {
val url = URL(urlString)
connection = url.openConnection() as HttpURLConnection
connection.doInput = true
connection.connect()
val inputStream = connection.inputStream
bitmap = BitmapFactory.decodeStream(inputStream)
} catch (e: Exception) {
Log.e("MainActivityKotlin", "Error downloading image", e)
} finally {
connection?.disconnect()
}
bitmap
}
}
使用第三方库 (强烈推荐)
在实际开发中,我们强烈建议使用成熟的第三方库,它们不仅简化了代码,还解决了缓存、图片加载(如圆角、圆形)、内存管理等一系列复杂问题。
推荐库:Glide (Google 官方推荐)
Glide 是一个快速、高效的图片加载和缓存库。

添加依赖
在 app/build.gradle.kts (或 app/build.gradle) 文件中添加:
dependencies {
implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' // 如果使用 Java
// 对于 Kotlin,使用 kapt
// kapt 'com.github.bumptech.glide:compiler:4.16.0'
}
在 XML 中添加网络权限 (同上)
在 Activity 或 Fragment 中使用
Glide 的使用极其简单,一行代码即可。
// Java
import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
public class MainActivityGlide extends AppCompatActivity {
private ImageView mImageView;
private String imageUrl = "https://example.com/path/to/your/image.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.imageView);
// 使用 Glide 加载图片
Glide.with(this)
.load(imageUrl)
.into(mImageView);
}
}
// Kotlin
import android.os.Bundle
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
class MainActivityGlideKotlin : AppCompatActivity() {
private lateinit var imageView: ImageView
private val imageUrl = "https://example.com/path/to/your/image.jpg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
imageView = findViewById(R.id.imageView)
// 使用 Glide 加载图片
Glide.with(this)
.load(imageUrl)
.into(imageView)
}
}
Glide 的优点:
- 自动缓存:内存缓存和磁盘缓存都自动处理,无需手动管理。
- 生命周期集成:自动感知 Activity/Fragment 的生命周期,在销毁时自动取消请求,避免内存泄漏。
- 强大的 API:支持圆角、圆形、裁剪、淡入淡出等多种变换。
- 高性能:高效的解码和内存管理策略。
重要注意事项和最佳实践
- 不要在主线程做网络操作:这是 Android 开发的铁律。
AsyncTask、Thread、HandlerThread、Kotlin Coroutines或RxJava都可以用来在后台线程执行网络请求。 - 处理图片内存:高清图片可能非常大,直接加载到内存
