《Android 應用開發基礎教程》——第十一章:Android 中的圖片加載與緩存(Glide 使用詳解)

目錄

第十一章:Android 中的圖片加載與緩存(Glide 使用詳解)

🔹 11.1 Glide 簡介

🔸 11.2 添加 Glide 依賴

🔸 11.3 基本用法

? 加載網絡圖片到 ImageView:

? 加載本地資源 / 文件 / URI:

🔸 11.4 占位圖、錯誤圖、縮略圖

🔸 11.5 圖片變換:圓角、圓形、裁剪

? CenterCrop 和 FitCenter:

? GlideTransform:實現圓角或圓形(需引入擴展庫):

🔸 11.6 緩存策略

🔸 11.7 在 RecyclerView 中使用 Glide

🔸 11.8 清除緩存

? 實戰練習建議

習題答案

項目結構

1. MainActivity.java

2. ImageTextAdapter.java

3. GlideUtils.java

4. CircleBorderTransform.java

5. activity_main.xml

6. item_image_text.xml

7. ImageTextItem.java

總結


第十一章:Android 中的圖片加載與緩存(Glide 使用詳解)

????????在移動應用中,圖片加載是最常見也最耗資源的任務之一。為了提升性能并避免內存泄露,我們通常使用圖片加載庫。Glide 是 Google 推薦的 Android 圖片加載庫,功能強大、使用簡單,支持圖片加載、轉換、緩存等操作。


🔹 11.1 Glide 簡介

Glide 由 BumpTech 開發,具有以下特點:

  • 支持從網絡、本地、資源中加載圖片

  • 自動內存緩存與磁盤緩存

  • 支持圖片縮放、裁剪、圓角、圓形

  • 支持 GIF 加載

  • 支持 RecyclerView 中高效加載


🔸 11.2 添加 Glide 依賴

build.gradle(:app) 文件中添加:

implementation 'com.github.bumptech.glide:glide:4.16.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'


🔸 11.3 基本用法

? 加載網絡圖片到 ImageView:

ImageView imageView = findViewById(R.id.imageView);Glide.with(this).load("https://example.com/image.jpg").into(imageView);


? 加載本地資源 / 文件 / URI:

// 資源圖片
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 占位圖、錯誤圖、縮略圖

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:

Glide.with(this).load(url).centerCrop()    // 居中裁剪.into(imageView);


? GlideTransform:實現圓角或圓形(需引入擴展庫):

implementation 'jp.wasabeef:glide-transformations:4.3.0'

import jp.wasabeef.glide.transformations.RoundedCornersTransformation;Glide.with(this).load(url).transform(new RoundedCornersTransformation(20, 0)) // 圓角半徑 20.into(imageView);


🔸 11.6 緩存策略

Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.ALL)  // 磁盤緩存策略.skipMemoryCache(false)                    // 是否跳過內存緩存.into(imageView);

常用策略包括:

策略描述
DiskCacheStrategy.ALL原圖和壓縮圖都緩存
DiskCacheStrategy.NONE不緩存任何內容
DiskCacheStrategy.RESOURCE僅緩存壓縮后的圖片

🔸 11.7 在 RecyclerView 中使用 Glide

@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 清除緩存

// 清除內存緩存(主線程)
Glide.get(context).clearMemory();// 清除磁盤緩存(子線程)
new Thread(() -> {Glide.get(context).clearDiskCache();
}).start();


? 實戰練習建議

  1. 實現一個圖文混排的 RecyclerView 列表,動態加載網絡圖片

  2. 使用 Glide 加載 GIF 動圖

  3. 用 GlideTransform 實現頭像圓形 + 外邊框效果

  4. 編寫工具類 GlideUtils 封裝通用加載邏輯


📢 下一章預告:

第十二章:Material Design 組件實戰(Toolbar、BottomNavigation、Snackbar 等)


習題答案

項目結構

MainActivity.java
ImageTextAdapter.java
GlideUtils.java
CircleBorderTransform.java
activity_main.xml
item_image_text.xml

1. MainActivity.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;@Overrideprotected 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

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@Overridepublic 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);}@Overridepublic 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 {// 普通圖片或 GIFGlideUtils.loadImage(context, item.getImageUrl(), holder.imageView);}holder.textView.setText(item.getDescription());}@Overridepublic 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

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 {// 加載普通圖片或 GIFpublic 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)); // 自定義 TransformGlide.with(context).load(url).apply(options).into(imageView);}
}

4. CircleBorderTransform.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;}@Overrideprotected 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;}@Overridepublic void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {messageDigest.update(("CircleBorderTransform" + borderWidth + borderColor).getBytes());}
}

5. 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:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="8dp" />
</LinearLayout>

6. item_image_text.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"><ImageViewandroid:id="@+id/imageView"android:layout_width="100dp"android:layout_height="100dp"android:scaleType="centerCrop"android:contentDescription="Image" /><TextViewandroid: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

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;}
}

總結

  1. 圖文混排:通過?RecyclerView?展示圖片和文字。
  2. 動態加載網絡圖片:使用?Glide?加載普通圖片和 GIF 動圖。
  3. 圓形頭像 + 邊框:通過自定義?CircleBorderTransform?實現。
  4. 工具類封裝GlideUtils?封裝了通用的圖片加載邏輯。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79112.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79112.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79112.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AE模板 300個故障干擾損壞字幕條標題動畫視頻轉場預設

這個AE模板提供了300個故障干擾損壞字幕條標題動畫視頻轉場預設&#xff0c;讓您的視頻具有炫酷的故障效果。無論是預告片、宣傳片還是其他類型的視頻&#xff0c;這個模板都能帶給您令人驚嘆的故障運動標題效果。該模板無需任何外置插件或腳本&#xff0c;只需一鍵點擊即可應用…

在 Python 中,以雙下劃線開頭和結尾的函數(如 `__str__`、`__sub__` 等)

在 Python 中&#xff0c;以雙下劃線開頭和結尾的函數&#xff08;如 __str__、__sub__ 等&#xff09;被稱為特殊方法&#xff08;Special Methods&#xff09;或魔術方法&#xff08;Magic Methods&#xff09;。它們確實是 Python 內置的&#xff0c;用于定義類的行為&#…

git問題記錄-如何切換歷史提交分支,且保留本地修改

問題記錄 我在本地編寫了代碼&#xff0c;突然想查看之前提交的代碼&#xff0c;并且想保留當前所在分支所做的修改 通過git stash對本地的代碼進行暫存 使用git checkout <commit-hash>切換到之前的提交記錄。 查看完之后我想切換回來&#xff0c;恢復暫存的本地代碼…

Github開通第三方平臺OAuth登錄及Java對接步驟

調研起因&#xff1a; 準備搞AI Agent海外項目&#xff0c;有相當一部分用戶群體是程序員&#xff0c;所以當然要接入Github這個全球最大的同性交友網站了&#xff0c;讓用戶使用Github賬號一鍵完成注冊或登錄。 本教程基于Web H5界面進行對接&#xff0c;同時也提供了spring-…

期刊、出版社、索引數據庫

image 1、研究人員向期刊或者會議投稿&#xff0c;交注冊費和相應的審稿費等相關費用[1]&#xff1b; 2、會議組織者和期刊聯系出版社&#xff0c;交出版費用&#xff1b; 3、出版社將論文更新到自己的數據庫中&#xff0c;然后將數據庫賣給全世界各大高校或企業&#xff1b; 4…

Transformer 模型及深度學習技術應用

近年來&#xff0c;隨著卷積神經網絡&#xff08;CNN&#xff09;等深度學習技術的飛速發展&#xff0c;人工智能迎來了第三次發展浪潮&#xff0c;AI技術在各行各業中的應用日益廣泛。 注意力機制&#xff1a;理解其在現代深度學習中的關鍵作用&#xff1b; Transformer模型…

zynq7035的arm一秒鐘最多可以支持觸發多少次中斷

一、概述 1.關于zynq7035的ARM處理器一秒能夠支持多少次中斷觸發&#xff0c;需要綜合來考慮。需要確定ARM處理器的參數&#xff0c;目前zynq7000系列&#xff0c;使用的雙核Cortex-A9處理器。其中主頻大概在500MHZ~1GHZ左右&#xff0c;不同的用戶配置的主頻可能稍微有差別。 …

數據結構與算法:圖論——最短路徑

最短路徑 先給出一些leetcode算法題&#xff0c;以后遇見了相關題目再往上增加 最短路徑的4個常用算法是Floyd、Bellman-Ford、SPFA、Dijkstra。不同應用場景下&#xff0c;應有選擇地使用它們&#xff1a; 圖的規模小&#xff0c;用Floyd。若邊的權值有負數&#xff0c;需要…

[android]MT6835 Android 關閉selinux方法

Selinux SELinux is an optional feature of the Linux kernel that provides support to enforce access control security policies to enforce MAC. It is based on the LSM framework. Working with SELinux on Android – LineageOS Android 關閉selinux MT6835 Android…

【Linux網絡編程】http協議的狀態碼,常見請求方法以及cookie-session

本文專欄&#xff1a;Linux網絡編程 目錄 一&#xff0c;狀態碼 重定向狀態碼 1&#xff0c;永久重定向&#xff08;301 Moved Permanently&#xff09; 2&#xff0c;臨時重定向&#xff08;302 Found&#xff09; 二&#xff0c;常見請求方法 1&#xff0c;HTTP常見Hea…

當神經網絡突破摩爾定律:探索大模型時代的算力新紀元

當摩爾定律熄滅后&#xff1a;AI算力革命如何重塑技術文明的底層邏輯 一、摩爾定律的黃昏&#xff1a;物理極限與經濟理性的雙重困境 當英特爾在1965年提出摩爾定律時&#xff0c;沒有人預料到這個每18-24個月將芯片晶體管數量翻倍的預言會成為現代計算文明的基石。半個世紀以…

位運算題目:尋找重復數

文章目錄 題目標題和出處難度題目描述要求示例數據范圍進階 前言解法一思路和算法代碼復雜度分析 解法二思路和算法代碼復雜度分析 解法三思路和算法代碼復雜度分析 題目 標題和出處 標題&#xff1a;尋找重復數 出處&#xff1a;287. 尋找重復數 難度 6 級 題目描述 要…

Elasticsearch:沒有 “AG” 的 RAG?

作者&#xff1a;來自 Elastic Gustavo Llermaly 了解如何利用語義搜索和 ELSER 構建一個強大且視覺上吸引人的問答體驗&#xff0c;而無需使用 LLMs。 想要獲得 Elastic 認證&#xff1f;查看下一期 Elasticsearch Engineer 培訓的時間&#xff01; Elasticsearch 擁有眾多新…

linux下安裝ollama網不好怎么辦?

文章目錄 前言kkgithub下載腳本,而不是直接運行修改腳本修改權限還是不行?前言 今天想在linux上面更新一下ollama,于是去到官網: https://ollama.com/download/linux linux下安裝ollama還是挺簡單的: curl -fsSL https://ollama.com/install.sh | sh我也是特別嗨皮地就…

相機-IMU聯合標定:相機-IMU外參標定

文章目錄 ??簡介??標定工具kalibr??標定數據錄制??相機-IMU外參標定??簡介 在 VINS(視覺慣性導航系統) 中,相機-IMU外參標定 是確保多傳感器數據時空統一的核心環節,其作用可概括為以下關鍵點: 坐標系對齊(空間同步),外參誤差會導致視覺特征點投影與IMU預積…

基于 Java 的實現前端組裝查詢語句,后端直接執行查詢方案,涵蓋前端和后端的設計思路

1. 前端設計 前端負責根據用戶輸入或交互條件,動態生成查詢參數,并通過 HTTP 請求發送到后端。 前端邏輯: 提供用戶界面(如表單、篩選器等),讓用戶選擇查詢條件。將用戶選擇的條件組裝成 JSON 格式的查詢參數。發送 HTTP 請求(如 POST 或 GET)到后端。示例: 假設用…

[STM32] 4-2 USART與串口通信(2)

文章目錄 前言4-2 USART與串口通信(2)數據發送過程雙緩沖與連續發送數據發送過程中的問題 數據接收過程TXE標志位&#xff08;發送數據寄存器空&#xff09;TC標志位&#xff08;發送完成標志位&#xff09;單個數據的發送數據的連續發送 接收過程中遇到的問題問題描述&#xf…

Qt多線程TCP服務器實現指南

在Qt中實現多線程TCP服務器可以通過為每個客戶端連接分配獨立的線程來處理&#xff0c;以提高并發性能。以下是一個分步實現的示例&#xff1a; 1. 自定義工作線程類&#xff08;處理客戶端通信&#xff09; // workerthread.h #include <QObject> #include <QTcpSo…

詳細介紹Python-pandas-DataFrame全部 *功能* 函數

Python-pandas-DataFrame全部 功能 函數 提示&#xff1a;幫幫志會陸續更新非常多的IT技術知識&#xff0c;希望分享的內容對您有用。本章分享的是pandas的使用語法。前后每一小節的內容是存在的有&#xff1a;學習and理解的關聯性。【幫幫志系列文章】&#xff1a;每個知識點…

香港科技大學廣州|可持續能源與環境學域博士招生宣講會—四川大學專場

香港科技大學廣州&#xff5c;可持續能源與環境學域博士招生宣講會—四川大學專場 時間&#xff1a;2025年5月8日&#xff08;星期四&#xff09;16:30開始 地點&#xff1a;四川大學基礎教學樓A座504 宣講嘉賓&#xff1a;肖殿勛 助理教授 一經錄取&#xff0c;享全額獎學金…