Glide 如何加載遠程 Base64 圖片

最近有個需求,后端給出的圖片地址并不是正常的 URL,而且需要一個接口去請求,但是返回的是 base64 數據流。這里不關心為啥要這么多,原因有很多,可能是系統的問題,也可能是能力問題。當然作為我們 Android 程序員,要緊的是如何解決這個問題。

首先我們拿到接口鏈接,我這次拿到的是這樣的:

https://www.example.com/cdn/attach/{fileId}/base64

這里的{fileId} 是指圖片的 id,那么正常的圖片地址可以理解為:

https://www.example.com/cdn/attach/1000/base64
https://www.example.com/cdn/attach/1002/base64

熟悉 Glide 加載邏輯的人,應該很熟悉,這種方式可能需要我們自定義ModelLoader 來解決問題,們可以讓 Glide 將 API 接口當作一種圖片源來處理,就像處理普通的圖片 URL 一樣。

實現方案

我們可以自定義 Base64ApiModelLoader 來處理 base64 的請求數據:

public class Base64ApiModelLoader implements ModelLoader<String, InputStream> {private static final String BASE_URL = "https://your-api-base-url/";private static final String API_PATH = "cdn/attach/";private final OkHttpClient okHttpClient;public Base64ApiModelLoader() {this.okHttpClient = new OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS).readTimeout(15, TimeUnit.SECONDS).build();}@Nullable@Overridepublic LoadData<InputStream> buildLoadData(@NonNull String fileId, int width, int height, @NonNull Options options) {// 創建緩存鍵,使用文件ID作為唯一標識Key key = new ObjectKey(API_PATH + fileId);// 返回加載數據,包含緩存鍵和數據獲取器return new LoadData<>(key, new Base64ApiFetcher(fileId, okHttpClient));}@Overridepublic boolean handles(@NonNull String model) {// 判斷是否是文件ID格式,這里簡單判斷不是URLreturn !model.startsWith("http") && !model.startsWith("data:");}// 工廠類,用于創建ModelLoaderpublic static class Factory implements ModelLoaderFactory<String, InputStream> {@NonNull@Overridepublic ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {return new Base64ApiModelLoader();}@Overridepublic void teardown() {// 清理資源}}// 數據獲取器,負責從API獲取Base64數據并轉換為InputStreamprivate static class Base64ApiFetcher implements DataFetcher<InputStream> {private final String fileId;private final OkHttpClient okHttpClient;private InputStream inputStream;private volatile boolean isCancelled;Base64ApiFetcher(String fileId, OkHttpClient okHttpClient) {this.fileId = fileId;this.okHttpClient = okHttpClient;}@Overridepublic void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {if (isCancelled) {callback.onLoadFailed(new IOException("Cancelled"));return;}// 構建API請求URLString apiUrl = BASE_URL + API_PATH + fileId + "/base64";Request request = new Request.Builder().url(apiUrl).build();try {// 執行請求Response response = okHttpClient.newCall(request).execute();if (!response.isSuccessful()) {callback.onLoadFailed(new IOException("Failed to load Base64 data: " + response.code()));return;}// 解析響應體ResponseBody responseBody = response.body();if (responseBody == null) {callback.onLoadFailed(new IOException("Empty response"));return;}// 解析JSON響應String jsonString = responseBody.string();JSONObject jsonObject = new JSONObject(jsonString);// 檢查響應碼int code = jsonObject.optInt("code", -1);if (code != 200) {callback.onLoadFailed(new IOException("API error: " + jsonObject.optString("message", "Unknown error")));return;}// 獲取Base64數據String base64Data = jsonObject.optString("data", "");if (base64Data.isEmpty()) {callback.onLoadFailed(new IOException("Empty Base64 data"));return;}// 處理可能存在的Data URI前綴if (base64Data.contains(",")) {base64Data = base64Data.split(",")[1];}// 解碼Base64數據byte[] imageBytes = Base64.decode(base64Data, Base64.DEFAULT);// 創建輸入流inputStream = new ByteArrayInputStream(imageBytes);// 回調成功callback.onDataReady(inputStream);} catch (IOException | JSONException | IllegalArgumentException e) {if (!isCancelled) {callback.onLoadFailed(e);}}}@Overridepublic void cleanup() {if (inputStream != null) {try {inputStream.close();} catch (IOException ignored) {// 忽略關閉錯誤}}}@Overridepublic void cancel() {isCancelled = true;}@NonNull@Overridepublic Class<InputStream> getDataClass() {return InputStream.class;}@NonNull@Overridepublic DataSource getDataSource() {return DataSource.REMOTE;}}
}

定義完成ModelLoader之后,我們可能就要注冊ModelLoader了。


@GlideModule
public class MyAppGlideModule extends AppGlideModule {@Overridepublic void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {super.registerComponents(context, glide, registry);// 注冊我們的自定義ModelLoader,用于處理Base64 API請求registry.append(String.class, InputStream.class, new Base64ApiModelLoader.Factory());}@Overridepublic boolean isManifestParsingEnabled() {return false;}
}

當然不能忘記需要有注解處理器

annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'

處理完之后,我們就可以這么調用了:

		Glide.with(imageView.getContext()).load(fileId)  // +.placeholder(R.mipmap.default_image).error(R.mipmap.default_image).into(imageView);

我們之前 load 方法中一直調用的是 url, 這里就直接調用 fileId 即可。因為我們已經定義了

registry.append(String.class, InputStream.class, new Base64ApiModelLoader.Factory());

其他地方都不變,即可正常進行請求了。

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

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

相關文章

004-nlohmann/json 快速認識-C++開源庫108杰

了解 nlohmann/json 的特點&#xff1b;理解編程中 “數據戰場”劃分的概念&#xff1b;迅速上手多種方式構建一個JSON對象&#xff1b; 1 特點與安裝 nlohmann/json 是一個在 github 長期霸占 “JSON” 熱搜版第1的CJSON處理庫。它的最大優點是與 C 標準庫的容器數據&#xf…

#基礎Machine Learning 算法(上)

機器學習算法的分類 機器學習算法大致可以分為三類&#xff1a; 監督學習算法 (Supervised Algorithms&#xff09;:在監督學習訓練過程中&#xff0c;可以由訓練數據集學到或建立一個模式&#xff08;函數 / learning model&#xff09;&#xff0c;并依此模式推測新的實例。…

正弦波、方波、三角波和鋸齒波信號發生器——Multisim電路仿真

目錄 Multisim使用教程說明鏈接 一、正弦波信號發生電路 1.1正弦波發生電路 電路組成 工作原理 振蕩頻率 1.2 正弦波發生電路仿真分析 工程文件鏈接 二、方波信號發生電路 2.1 方波發生電路可調頻率 工作原理 詳細過程 2.2 方波發生電路可調頻率/可調占空比 調節占空比 方波產生…

【AND-OR-~OR鎖存器設計】2022-8-31

緣由鎖存器11111111111-硬件開發-CSDN問答 重置1&#xff0c;不論輸入什么&#xff0c;輸出都為0&#xff1b; 重置0&#xff0c;輸入1就鎖住1 此時輸入再次變為0&#xff0c;輸出不變&#xff0c;為鎖住。

力扣-字符串-468 檢查ip

思路 考察字符串的使用&#xff0c;還有對所有邊界條件的檢查 spilt&#xff08;“\.”&#xff09;&#xff0c;toCharArray&#xff0c;Integer.parseInt() 代碼 class Solution {boolean checkIpv4Segment(String str){if(str.length() 0 || str.length() > 4) retur…

BC8 十六進制轉十進制

題目&#xff1a;BC8 十六進制轉十進制 描述 BoBo寫了一個十六進制整數ABCDEF&#xff0c;他問KiKi對應的十進制整數是多少。 輸入描述&#xff1a; 無 輸出描述&#xff1a; 十六進制整數ABCDEF對應的十進制整數&#xff0c;所占域寬為15。 備注&#xff1a; printf可以使用…

ARM子程序和棧

微處理器中的棧由棧指針指向存儲器中的棧頂來實現&#xff0c;當數據項入棧時&#xff0c;棧 指針向上移動&#xff0c;當數據項出棧時&#xff0c;棧指針向下移動。 實現棧時需要做出兩個決定&#xff1a;一是當數據項進棧時是向低位地址方向向上生 長&#xff08;圖a和圖b&a…

jwt身份驗證和基本的利用方式

前言 &#xff1a; 什么是jwt&#xff08;json web token&#xff09;&#xff1f; 看看英文單詞的意思就是 json形式的token 他的基本的特征 &#xff1a; 類似于這樣的 他有2個點 分割 解碼的時候會有三個部分 頭部 payload 對稱密鑰 這個就是對稱加密 頭部&am…

n8n工作流自動化平臺的實操:利用本地嵌入模型,完成文件內容的向量化及入庫

1.成果展示 1.1n8n的工作流 牽涉節點&#xff1a;FTP、Code、Milvus Vector Store、Embeddings OpenAI、Default Data Loader、Recursive Character Text Splitter 12.向量庫的結果 2.實操過程 2.1發布本地嵌入模型服務 將bge-m3嵌入模型&#xff0c;發布成滿足open api接口…

MATLAB人工大猩猩部隊GTO優化CNN-LSTM多變量時間序列預測

本博客來源于CSDN機器魚&#xff0c;未同意任何人轉載。 更多內容&#xff0c;歡迎點擊本專欄目錄&#xff0c;查看更多內容。 目錄 0 引言 1 數據準備 2 CNN-LSTM模型搭建 3 GTO超參數優化 3.1 GTO函數極值尋優 3.2 GTO優化CNN-LSTM超參數 3.3 主程序 4 結語 0 引言…

git項目遷移,包括所有的提交記錄和分支 gitlab遷移到gitblit

之前git都是全新項目上傳&#xff0c;沒有遷移過&#xff0c;因為遷移的話要考慮已有項目上的分支都要遷移過去&#xff0c;提交記錄能遷移就好&#xff1b;分支如果按照全新項目上傳的方式需要新git手動創建好老git已有分支&#xff0c;在手動一個一個克隆老項目分支代碼依次提…

Photo-SLAM論文理解、環境搭建、代碼理解與實測效果

前言&#xff1a;第一個解耦式Photo-SLAM&#xff0c;亮點和效果。 參考&#xff1a;https://zhuanlan.zhihu.com/p/715311759 全網最細PhotoSLAM的conda環境配置教程&#xff0c;拒絕環境污染&#xff01;&#xff01;-CSDN博客 1. 環境搭建 硬件&#xff1a;RTX 4090D wi…

如何使用VSCode編寫C、C++和Python程序

一、首先準備好前期工作。如下載安裝Python、VSCode、一些插件等。寫代碼之前需要先創建文件夾和文件。 二、將不同語言寫的代碼放在不同的文件夾中&#xff0c;注意命名時不要使用中文。 三、打開VSCode&#xff0c;點擊“文件”->“打開文件夾”->“daimalainxi”->…

基于不確定性感知學習的單圖像自監督3D人體網格重建 (論文筆記與思考)

文章目錄 論文解決的問題提出的算法以及啟發點 論文解決的問題 首先這是 Self-Supervised 3D Human mesh recovery from a single image with uncertainty-aware learning &#xff08;AAAI 2024&#xff09;的論文筆記。該文中主要提出了一個自監督的framework用于人體的姿態…

Leetcode刷題記錄33——二叉樹的最小深度

題源&#xff1a;https://leetcode.cn/problems/minimum-depth-of-binary-tree/description/ 題目描述&#xff1a; 思路一&#xff1a; 使用 DFS 遞歸遍歷的解法&#xff0c;每當遍歷到一條樹枝的葉子節點&#xff0c;就會更新最小深度&#xff0c;當遍歷完整棵樹后&#x…

有效的括號(20)

20. 有效的括號 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:bool isValid(string s) {unordered_map<char, char> m {{), (}, {],[}, {}, {}};stack<char> stk;for (int i 0; i < s.size(); i) {if (s[i] ( || s[i…

電子郵件相關協議介紹

0 Preface/Foreword 1 協議介紹 電子郵件包含的主要協議&#xff1a; SMTPPOPIMAP 1.1 SMPT SMPT: Simple Mail Transfer Protocol&#xff0c;電子郵件傳輸的標準協議&#xff0c;負責將郵件從發送方傳輸到接收方郵件服務器。 1.2 POP POP&#xff1a; Post Office Protoc…

Linux壓縮和解壓類

一、gzip/gunzip 壓縮 1、基本語法 gzip 文件 &#xff08;功能描述&#xff1a;壓縮文件&#xff0c;只能將文件壓縮為*.gz文件&#xff09; gunzip 文件.gz &#xff08;功能描述&#xff1a;解壓縮文件命令&#xff09; 2、經驗技巧 &#xff08;1&#…

力扣hot100 (除自身以外數組的乘積)

238. 除自身以外數組的乘積 中等 給你一個整數數組 nums&#xff0c;返回 數組 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘積 。 題目數據 保證 數組 nums之中任意元素的全部前綴元素和后綴的乘積都在 32 位 整數范圍內。 請 不要使用除…

什么是“系統調用”

一、什么是“系統調用”&#xff1f;用生活中的比喻理解 可以把“系統調用”比作你&#xff08;用戶&#xff09;向“管理員”請求幫助完成某件事情的過程。 舉個例子&#xff1a; 你想借書&#xff0c;去圖書館&#xff08;操作系統&#xff09;找管理員&#xff08;內核&a…