
目录
[第十一章:Android 中的图片加载与缓存(Glide 使用详解)](#第十一章:Android 中的图片加载与缓存(Glide 使用详解))
[🔹 11.1 Glide 简介](#🔹 11.1 Glide 简介)
[🔸 11.2 添加 Glide 依赖](#🔸 11.2 添加 Glide 依赖)
[🔸 11.3 基本用法](#🔸 11.3 基本用法)
[✦ 加载网络图片到 ImageView:](#✦ 加载网络图片到 ImageView:)
[✦ 加载本地资源 / 文件 / URI:](#✦ 加载本地资源 / 文件 / URI:)
[🔸 11.4 占位图、错误图、缩略图](#🔸 11.4 占位图、错误图、缩略图)
[🔸 11.5 图片变换:圆角、圆形、裁剪](#🔸 11.5 图片变换:圆角、圆形、裁剪)
[✦ CenterCrop 和 FitCenter:](#✦ CenterCrop 和 FitCenter:)
[✦ GlideTransform:实现圆角或圆形(需引入扩展库):](#✦ GlideTransform:实现圆角或圆形(需引入扩展库):)
[🔸 11.6 缓存策略](#🔸 11.6 缓存策略)
[🔸 11.7 在 RecyclerView 中使用 Glide](#🔸 11.7 在 RecyclerView 中使用 Glide)
[🔸 11.8 清除缓存](#🔸 11.8 清除缓存)
[✅ 实战练习建议](#✅ 实战练习建议)
[1. MainActivity.java](#1. MainActivity.java)
[2. ImageTextAdapter.java](#2. ImageTextAdapter.java)
[3. GlideUtils.java](#3. GlideUtils.java)
[4. CircleBorderTransform.java](#4. CircleBorderTransform.java)
[5. activity_main.xml](#5. activity_main.xml)
[6. item_image_text.xml](#6. item_image_text.xml)
[7. ImageTextItem.java](#7. ImageTextItem.java)
第十一章:Android 中的图片加载与缓存(Glide 使用详解)
在移动应用中,图片加载是最常见也最耗资源的任务之一。为了提升性能并避免内存泄露,我们通常使用图片加载库。Glide 是 Google 推荐的 Android 图片加载库,功能强大、使用简单,支持图片加载、转换、缓存等操作。
🔹 11.1 Glide 简介
Glide 由 BumpTech 开发,具有以下特点:
-
支持从网络、本地、资源中加载图片
-
自动内存缓存与磁盘缓存
-
支持图片缩放、裁剪、圆角、圆形
-
支持 GIF 加载
-
支持 RecyclerView 中高效加载
🔸 11.2 添加 Glide 依赖
在 build.gradle(:app)
文件中添加:
java
implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
🔸 11.3 基本用法
✦ 加载网络图片到 ImageView:
java
ImageView imageView = findViewById(R.id.imageView);
Glide.with(this)
.load("https://example.com/image.jpg")
.into(imageView);
✦ 加载本地资源 / 文件 / URI:
java
// 资源图片
Glide.with(this)
.load(R.drawable.sample)
.into(imageView);
// 本地文件
File file = new File(getExternalFilesDir(null), "pic.jpg");
Glide.with(this)
.load(file)
.into(imageView);
🔸 11.4 占位图、错误图、缩略图
java
Glide.with(this)
.load("https://example.com/image.jpg")
.placeholder(R.drawable.loading) // 加载中显示的图
.error(R.drawable.error_image) // 加载失败显示的图
.thumbnail(0.1f) // 显示缩略图
.into(imageView);
🔸 11.5 图片变换:圆角、圆形、裁剪
✦ CenterCrop 和 FitCenter:
java
Glide.with(this)
.load(url)
.centerCrop() // 居中裁剪
.into(imageView);
✦ GlideTransform:实现圆角或圆形(需引入扩展库):
javascript
implementation 'jp.wasabeef:glide-transformations:4.3.0'
java
import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
Glide.with(this)
.load(url)
.transform(new RoundedCornersTransformation(20, 0)) // 圆角半径 20
.into(imageView);
🔸 11.6 缓存策略
java
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL) // 磁盘缓存策略
.skipMemoryCache(false) // 是否跳过内存缓存
.into(imageView);
常用策略包括:
策略 | 描述 |
---|---|
DiskCacheStrategy.ALL |
原图和压缩图都缓存 |
DiskCacheStrategy.NONE |
不缓存任何内容 |
DiskCacheStrategy.RESOURCE |
仅缓存压缩后的图片 |
🔸 11.7 在 RecyclerView 中使用 Glide
java
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Glide.with(holder.itemView.getContext())
.load(itemList.get(position).getImageUrl())
.into(holder.imageView);
}
注意:不要在 Adapter 中使用
with(context.getApplicationContext())
,会影响 View 生命周期管理。
🔸 11.8 清除缓存
java
// 清除内存缓存(主线程)
Glide.get(context).clearMemory();
// 清除磁盘缓存(子线程)
new Thread(() -> {
Glide.get(context).clearDiskCache();
}).start();
✅ 实战练习建议
-
实现一个图文混排的 RecyclerView 列表,动态加载网络图片
-
使用 Glide 加载 GIF 动图
-
用 GlideTransform 实现头像圆形 + 外边框效果
-
编写工具类
GlideUtils
封装通用加载逻辑
📢 下一章预告:
第十二章:Material Design 组件实战(Toolbar、BottomNavigation、Snackbar 等)
习题答案
项目结构
javascript
MainActivity.java
ImageTextAdapter.java
GlideUtils.java
CircleBorderTransform.java
activity_main.xml
item_image_text.xml
1. MainActivity.java
java
package com.example.demo;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ImageTextAdapter adapter;
private List<ImageTextItem> itemList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 模拟数据
itemList = new ArrayList<>();
itemList.add(new ImageTextItem("https://example.com/image1.jpg", "这是描述文字 1"));
itemList.add(new ImageTextItem("https://example.com/image2.gif", "这是描述文字 2"));
itemList.add(new ImageTextItem("https://example.com/avatar.png", "这是圆形头像"));
adapter = new ImageTextAdapter(itemList, this);
recyclerView.setAdapter(adapter);
}
}
2. ImageTextAdapter.java
java
package com.example.demo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
public class ImageTextAdapter extends RecyclerView.Adapter<ImageTextAdapter.ViewHolder> {
private List<ImageTextItem> itemList;
private Context context;
public ImageTextAdapter(List<ImageTextItem> itemList, Context context) {
this.itemList = itemList;
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_image_text, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ImageTextItem item = itemList.get(position);
// 使用 Glide 加载图片
if (position == 2) {
// 使用圆形头像 + 边框效果
GlideUtils.loadCircleWithBorder(context, item.getImageUrl(), holder.imageView, 5, R.color.teal_200);
} else {
// 普通图片或 GIF
GlideUtils.loadImage(context, item.getImageUrl(), holder.imageView);
}
holder.textView.setText(item.getDescription());
}
@Override
public int getItemCount() {
return itemList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
textView = itemView.findViewById(R.id.textView);
}
}
}
3. GlideUtils.java
java
package com.example.demo;
import android.content.Context;
import android.graphics.Color;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
public class GlideUtils {
// 加载普通图片或 GIF
public static void loadImage(Context context, String url, ImageView imageView) {
Glide.with(context)
.load(url)
.into(imageView);
}
// 加载圆形头像 + 边框效果
public static void loadCircleWithBorder(Context context, String url, ImageView imageView, int borderWidth, int borderColor) {
RequestOptions options = new RequestOptions()
.transform(new CircleBorderTransform(borderWidth, borderColor)); // 自定义 Transform
Glide.with(context)
.load(url)
.apply(options)
.into(imageView);
}
}
4. CircleBorderTransform.java
java
package com.example.demo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import androidx.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import java.security.MessageDigest;
public class CircleBorderTransform extends BitmapTransformation {
private final int borderWidth;
private final int borderColor;
public CircleBorderTransform(int borderWidth, int borderColor) {
this.borderWidth = borderWidth;
this.borderColor = borderColor;
}
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
int diameter = Math.min(toTransform.getWidth(), toTransform.getHeight());
int radius = diameter / 2;
Bitmap result = pool.get(diameter + borderWidth * 2, diameter + borderWidth * 2, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setAntiAlias(true);
// 绘制圆形头像
RectF rectF = new RectF(borderWidth, borderWidth, diameter + borderWidth, diameter + borderWidth);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(toTransform, null, rectF, paint);
// 绘制边框
paint.setXfermode(null);
paint.setColor(borderColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(borderWidth);
canvas.drawOval(rectF, paint);
return result;
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(("CircleBorderTransform" + borderWidth + borderColor).getBytes());
}
}
5. activity_main.xml
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:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp" />
</LinearLayout>
6. item_image_text.xml
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="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:contentDescription="Image" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Description"
android:textSize="16sp"
android:paddingStart="16dp"
android:gravity="center_vertical" />
</LinearLayout>
7. ImageTextItem.java
java
package com.example.demo;
public class ImageTextItem {
private String imageUrl;
private String description;
public ImageTextItem(String imageUrl, String description) {
this.imageUrl = imageUrl;
this.description = description;
}
public String getImageUrl() {
return imageUrl;
}
public String getDescription() {
return description;
}
}
总结
- 图文混排 :通过
RecyclerView
展示图片和文字。 - 动态加载网络图片 :使用
Glide
加载普通图片和 GIF 动图。 - 圆形头像 + 边框 :通过自定义
CircleBorderTransform
实现。 - 工具类封装 :
GlideUtils
封装了通用的图片加载逻辑。