Android:如何将动态URL图片加载到自定义ImageView类中
自定义ImageView加载动态URL图片的完善方案
嘿,我来帮你梳理下这个自定义ImageView的实现问题,先说说当前写法的几个小坑,再给你完善后的代码方案~
当前实现的问题
- 构造函数中直接加载图片的风险:View的构造函数执行时,它还没完成布局测量,Glide可能无法正确获取ImageView的尺寸,导致图片适配出问题;而且当屏幕旋转等配置变更时,View会被重建,重复加载图片会浪费资源。
- 构造函数覆盖不完整:你只写了两个构造函数,AppCompatImageView还有第三个带
defStyleAttr参数的构造函数,如果在XML布局中使用这个View,会因为找不到匹配的构造函数而崩溃。 - 没有异常处理:如果
SessionManager返回的图片URL为空、或者CountryWiseDataObject为null,会直接导致Glide加载失败,没有 fallback 方案,用户体验不好。 - 生命周期绑定不当:直接用传入的
context绑定Glide请求,当这个context(比如Activity)销毁时,可能会引发内存泄漏。
完善后的完整代码
import android.content.Context; import android.util.AttributeSet; import android.widget.ImageView; import androidx.appcompat.widget.AppCompatImageView; import android.text.TextUtils; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; public class CustomLocalCurrencyImageViewWhiteColor extends AppCompatImageView { public CustomLocalCurrencyImageViewWhiteColor(Context context) { super(context); initView(); } public CustomLocalCurrencyImageViewWhiteColor(Context context, AttributeSet attrs) { super(context, attrs); initView(); } public CustomLocalCurrencyImageViewWhiteColor(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(); } // 初始化View的基础配置 private void initView() { // 根据需求设置默认的缩放类型,比如fitCenter或者centerCrop setScaleType(ImageView.ScaleType.FIT_CENTER); } // 当View被添加到窗口时加载图片,此时View已完成初始化 @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); loadCurrencyImage(); } // 核心图片加载逻辑 private void loadCurrencyImage() { Context context = getContext(); if (context == null) { return; } // 先处理Session数据为空的情况 CountryWiseData countryData = SessionManager.getCountryWiseDataObject(context); if (countryData == null) { setDefaultImage(); return; } String currencyImageUrl = countryData.getCurrencyImageWhite(); // 处理URL为空的情况 if (TextUtils.isEmpty(currencyImageUrl)) { setDefaultImage(); return; } // 使用Glide加载,绑定View的生命周期(AndroidX的View自带LifecycleOwner实现) Glide.with(this) .load(currencyImageUrl) .placeholder(R.drawable.ic_loading_currency) // 加载时的占位图,自己替换成你的资源 .error(R.drawable.ic_default_currency_white) // 加载失败时的默认图 .transition(DrawableTransitionOptions.withCrossFade()) // 添加淡入过渡动画,提升体验 .fitCenter() // 适配设置的scaleType .into(this); } // 设置默认图片的封装方法 private void setDefaultImage() { setImageResource(R.drawable.ic_default_currency_white); } // 提供外部调用的刷新方法,比如切换国家后主动刷新图片 public void refreshCurrencyImage() { loadCurrencyImage(); } }
关键改进说明
- 完整覆盖构造函数:确保在XML中使用这个View不会崩溃。
- 延迟加载时机:把图片加载移到
onAttachedToWindow(),此时View已经完成布局,能正确获取尺寸,避免适配问题;同时Glide会自动跟随View的生命周期,在View被移除时取消请求,防止内存泄漏。 - 完善异常处理:增加了Session数据为空、URL为空的判断,提供默认图片兜底。
- 增强用户体验:添加了加载占位图、错误图和淡入过渡动画。
- 提供刷新接口:当货币数据变化时(比如用户切换国家),可以直接调用
refreshCurrencyImage()刷新图片,不需要重建View。
额外注意事项
- 添加Glide依赖:确保在Module的
build.gradle中添加Glide的最新依赖:
implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
- 网络权限:如果图片是网络URL,记得在
AndroidManifest.xml中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
- 资源替换:把代码中的占位图、错误图资源替换成你项目中实际的资源ID。
内容的提问来源于stack exchange,提问作者user9091958
相关产品推荐
相关产品推荐

