背景
说到异常处理,你可能直接会认为不就是 try-catch 的事情,至于写一篇文章单独来说明吗?
如果你是这么想的,那么本篇说不定会给你惊喜哦~
而且本篇聚焦在图片的异常处理。
场景
学以致用,有具体的应用场景,能够加深我们对知识的掌握。
我们以简书的文章列表为例,如下图:
假设产品有这样的需求,当右边的封面图加载失败的时候,用一个默认图片替换或者直接让文本横向填充原有图片位置。
不管处理方式是怎样,首先我们要做的就是能够知道图片加载失败。
如何获知图片加载失败呢?下面我们通过 Flutter 自带网络加载 API 和一个第三方网络库来进行对比说明。
Image.network
我们看下源码,如下:
Image.network(String src, {
Key key,
double scale = 1.0,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
Map<String, String> headers,
}) : image = NetworkImage(src, scale: scale, headers: headers),
assert(alignment != null),
assert(repeat != null),
assert(matchTextDirection != null),
super(key: key);
可以看到只有 src 是必填参数,因此我们给出 src 为不同值的情况。
1.一个图片的 url
Widget _buildWidget() {
return Image.network('https://upload-images.jianshu.io/upload_images/5361063-e413832da0038304.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/800');
}
能够正常显示如下图:
2.不可访问 url,如随便一个字符串 test
Widget _buildWidget() {
return Image.network('test');
}
终端报错如下:
flutter: ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════
flutter: The following ArgumentError was thrown resolving an image codec:
flutter: Invalid argument(s): No host specified in URI file:///test
模拟器显示空白。
这种场景假设我们要捕获异常,增加 try-catch,如下:
Widget _buildWidget() {
try {
return Image.network('test');
} catch (e) {
print('enter catch exception start');
print(e);
print('enter catch exception end');
return Container();
}
}
依然没法捕获
3.可访问非图片 url,比如 http://mp.weixin.qq.com/mp/homepage?__biz=MzI3OTAyNzAwNg==&hid=5&sn=7e4598d8b00537fe2846f2e85d746b9a&scene=18#wechat_redirect
Widget _buildWidget() {
try {
return Image.network('http://mp.weixin.qq.com/mp/homepage?__biz=MzI3OTAyNzAwNg==&hid=5&sn=7e4598d8b00537fe2846f2e85d746b9a&scene=18#wechat_redirect');
} catch (e) {
print('enter catch exception start');
print(e);
print('enter catch exception end');
return Container();
}
}
控制台抛出如下异常
[VERBOSE-2:codec.cc(97)] Failed decoding image. Data is either invalid, or it is encoded using an unsupported format.
flutter: ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════
flutter: The following _Exception was thrown resolving an image codec:
flutter: Exception: operation failed
可以看到 try-catch 一样没法生效。没有打印相关日志。
cached_network_image
这是一个第三方开发的网络库,pub 地址为 https://pub.dartlang.org/packages/cached_network_image
因为项目有用到这个库,所以用这个来举例,并不是为其打广告,至于你实际开发是否用这个库,还是有其他更好的库,需要你自己去评估。
因为这个是项目组 iOS 同事选择的,我这边并没有深入研究过。
我们仿照上面的依次执行 3 种 case。
1.一个图片的 url
Widget _buildWidget() {
return Image(image: new CachedNetworkImageProvider('https://upload-images.jianshu.io/upload_images/5361063-e413832da0038304.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/800'));
}
能够正常显示如下图:
2.不可访问 url,如随便一个字符串 test
Widget _buildWidget() {
return Image(image: new CachedNetworkImageProvider('test'));
}
终端报错如下:
flutter: ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞═══════════