在flutter开发中,当App项目内存吃紧时,页面中如果图片很多时需要及时清理,如果不能及时清理,会造成内存泄漏,导致App卡顿甚至强制退出或手机死机。
这里我使用extended_image封装了一个全局可用的Widget,亲测IOS和安卓好用。
首先在pubspec.yaml文件中配置插件并下载,执行Pub get。
dependencies:
extended_image: ^6.2.0
我使用的是6.2.0版本,基于ExtendedImage我对netWork网络图片组件做了如下封装,内有注释与备注,就不做过多的解释了,完全都能看的懂!
class JudgeNetworkImage extends StatefulWidget {
const JudgeNetworkImage(
this.url, {
Key? key,
this.width,
this.height,
this.isAvatar = false,
this.fit = BoxFit.cover,
this.borderRadius,
this.shape,
this.borderWidth = 0.0,
this.borderColor,
this.opacity = 1.0,
this.scale = 1.0,
this.maxBytes,
this.filterQuality = FilterQuality.low,
this.repeat = ImageRepeat.noRepeat,
this.replaceImgPlayback = false,
this.enableMemoryCache = true,
this.clearMemoryCacheIfFailed = true,
this.clearMemoryCacheWhenDispose = true,
this.cacheRawData = false,
this.placeholder,
this.errorWidget,
this.loadingWidget,
this.defaultImagePath,
}) : super(key: key);
final String url; // 图片URL
final double? width; // 宽度
final double? height; // 高度
final bool isAvatar; // 是否为头像
final BoxFit fit; // 适配方式
final BorderRadius? borderRadius; // 圆角
final BoxShape? shape; // 形状(圆形/矩形)
final double borderWidth; // 边框宽度
final Color? borderColor; // 边框颜色
final double opacity; // 透明度
final double scale; // 缩放比例
final int? maxBytes; // 控制图片加载时的字节大小限制
final FilterQuality filterQuality; // 缩放质量
final ImageRepeat repeat; // 重复方式
final bool replaceImgPlayback; // 更换图片时是否保留旧图
final bool enableMemoryCache; // 启用内存缓存
final bool clearMemoryCacheIfFailed; // 加载失败时清除缓存
final bool clearMemoryCacheWhenDispose; // 组件销毁时清除缓存
final bool cacheRawData; // 缓存原始数据
final Widget? placeholder; // 加载中占位图
final Widget? errorWidget; // 加载失败组件
final Widget? loadingWidget; // 加载中组件
final String? defaultImagePath; // 默认图片路径
@override
State<JudgeNetworkImage> createState() => _JudgeNetworkImageState();
}
class _JudgeNetworkImageState extends State<JudgeNetworkImage> {
late String _url;
@override
void initState() {
super.initState();
_url = widget.url;
}
@override
void dispose() {
super.dispose();
if (widget.clearMemoryCacheWhenDispose) {
// 主动清除图片缓存
if (_url.isNotEmpty && _url != (widget.defaultImagePath ?? '')) {
final provider = ExtendedNetworkImageProvider(_url);
provider.evict();
}
}
}
@override
Widget build(BuildContext context) {
Widget child = Container(
width: widget.width ?? double.maxFinite,
height: widget.height ?? double.maxFinite,
decoration: BoxDecoration(
// 边框部分
border: widget.borderWidth > 0
? Border.all(
color: widget.borderColor ?? Colors.transparent,
width: widget.borderWidth,
)
: null,
),
child: ExtendedImage.network(
_url,
width: widget.width,
height: widget.height,
fit: widget.fit,
scale: widget.scale,
filterQuality: widget.filterQuality,
repeat: widget.repeat,
gaplessPlayback: widget.replaceImgPlayback,
enableMemoryCache: widget.enableMemoryCache,
clearMemoryCacheIfFailed: widget.clearMemoryCacheIfFailed,
clearMemoryCacheWhenDispose: widget.clearMemoryCacheWhenDispose,
cacheRawData: widget.cacheRawData,
maxBytes: widget.maxBytes,
// 应用透时度
color: widget.opacity < 1.0
? Colors.white.withOpacity(widget.opacity)
: null,
colorBlendMode: widget.opacity < 1.0 ? BlendMode.srcIn : null,
clipBehavior: Clip.none,
// 加载状态回调
loadStateChanged: (state) {
return _handleLoadState(state);
},
),
);
if (widget.shape == BoxShape.circle) {
return ClipOval(
child: child,
);
} else if (widget.borderRadius != null) {
return ClipRRect(
borderRadius: widget.borderRadius,
child: child,
);
} else {
return child;
}
}
/// 处理加载状态
Widget _handleLoadState(ExtendedImageState state) {
switch (state.extendedImageLoadState) {
case LoadState.loading:
// 加载中显示指示器
return SizedBox(
width: widget.width != null ? widget.width! * 0.4 : 42.rpx,
child: Center(
child: CircularProgressIndicator(
valueColor:
const AlwaysStoppedAnimation<Color>(AppColors.success),
strokeWidth: 4.rpx,
),
),
);
case LoadState.completed:
return state.completedWidget;
case LoadState.failed:
// 加载失败 - 显示默认图片并清除缓存
_clearCacheOnError(state);
return Container(
color: const Color(0xFFF2F2F2),
alignment: Alignment.center,
child: widget.isAvatar
? Image.asset(
'${AppGlobal.imgUrl}man_presuppose.png',
fit: BoxFit.fill,
)
: Image.asset(
'${AppGlobal.imgUrl}not_pic.png',
width: widget.width != null ? widget.width! * 0.6 : 64.rpx,
fit: BoxFit.fitWidth,
),
);
}
}
void _clearCacheOnError(ExtendedImageState state) {
if (widget.clearMemoryCacheIfFailed && mounted) {
// 获取图片提供者并清除缓存
if (state.imageProvider is ExtendedNetworkImageProvider) {
final provider = state.imageProvider as ExtendedNetworkImageProvider;
provider.evict();
}
}
}
}
以上就是一个完整的网络图片widget的封装,对性能提升有相当大的帮助!