通常我们加载网络图片会使用官方自带的Image控件,例如:
Image.network("https://www.gravatar.com/avatar/07e417fe88e9aed744c300d52148bf4a?s=328&d=identicon&r=PG&f=1");
一旦加载的URL地址错误,或者网络加载失败都会抛出异常,而且该方法并没有提供失败或者错误回调,这样我们就没有办法在合适的时机替换上失败的占位图。
经过一番查询后使用一下方式可以获取图片加载成功和失败的回调:
static Image getImage(String url, [double w, double h, Function() onError]) {
var image = Image.network(url, width: w, height: h);
var resolve = image.image.resolve(ImageConfiguration.empty);
resolve.addListener(ImageStreamListener((_, __) {
print("image success.");
}, onError: (dynamic exception, StackTrace stackTrace) {
print("image err.");
onError();
}));
return image;
}
由于回调就意味着异步,所以操作起来并不是很方便,这才又了封装这一说。
创建ImageWidget.dart文件:
import 'package:flutter/material.dart';
//封装图片加载控件,增加图片加载失败时加载默认图片
class ImageWidget extends StatefulWidget {
ImageWidget({@required this.url, this.w, this.h, this.defImagePath = "assets/images/ic_launcher_round.png"});
final String url;
final double w;
final double h;
final String defImagePath;
@override
State<StatefulWidget> createState() {
return _StateImageWidget();
}
}
class _StateImageWidget extends State<ImageWidget> {
Image _image;
@override
void initState() {
super.initState();
_image = Image.network(
widget.url,
width: widget.w,
height: widget.h,
);
var resolve = _image.image.resolve(ImageConfiguration.empty);
resolve.addListener(ImageStreamListener((_, __) {
//加载成功
}, onError: (dynamic exception, StackTrace stackTrace) {
//加载失败
setState(() {
_image = Image.asset(
widget.defImagePath,
width: widget.w,
height: widget.h,
);
});
}));
}
@override
Widget build(BuildContext context) {
return _image;
}
}
控件向外暴露图片地址,控件宽高和占位图。其他属性可自行扩展。
在图片加载失败时调用setState重新创建默认占位图,并通知刷新UI。