Image.network()失败时,无法捕获NetworkImageLoadException



我使用Image.network((显示URL中的图像就是这样用的

Image image = Image.network(
_auth.currentUser!.photoURL!,
width: 100.getWidth(context),
height: 100.getWidth(context),
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
return wasSynchronouslyLoaded
? child
: _profileImagePlaceholder(context);
},
loadingBuilder: (context, child, loadingProgress) {
return loadingProgress == null
? child
: _profileImagePlaceholder(context);
},
errorBuilder: (context, error, stackTrace) {
return _profileImagePlaceholder(context);
},
);

但即使我设置了errorBuilder,甚至用try/catch包装整个过程此NetworkImageLoadException仍显示

完全异常

The following NetworkImageLoadException was thrown resolving an image codec:
HTTP request failed, statusCode: 403,

When the exception was thrown, this was the stack:
#0      NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:99:9)
<asynchronous suspension>
...
Image provider:
NetworkImage("https://firebasestorage.googleapis.com/v0/b/biddee-co.appspot.com/o/profiles%2FdefaultProfile.png?alt=media&token=a4a99031-aabd-4597-b075-77ecb2d3e594",
scale: 1.0)
Image key:
NetworkImage("https://firebasestorage.googleapis.com/v0/b/biddee-co.appspot.com/o/profiles%2FdefaultProfile.png?alt=media&token=a4a99031-aabd-4597-b075-77ecb2d3e594",
scale: 1.0)

在当前版本的Flutter中,这些都不适用。这就是对我有效的方法。

import 'package:http/http.dart';
...
final String url;
...
class _WebIconState extends State<WebIcon> {
late Widget imgWidget;
late bool loaded;
@override
void initState() {
imgWidget = SizedBox.shrink();
loaded = false;
super.initState();
}
@override
Widget build(BuildContext context) {
Uri? uri = Uri.tryParse(widget.url);
if (uri == null) {
return SizedBox.shrink();
}
if (!loaded) {
() async {
Response resp = await get(uri);
if (resp.statusCode >= 200 &&
resp.statusCode < 300 &&
resp.headers["content-type"] is String &&
resp.headers["content-type"]!.contains("image")) {
setState(() {
imgWidget = Image.memory(resp.bodyBytes);
loaded = true;
});
}
log("Loaded ${widget.url}");
}();
}
return imgWidget;
}

在我的例子中,在生产代码中修复它的方法是在图像解析中添加一个带有onError:的侦听器

final image = Image.network(
// Properties.
errorBuilder: // ...,
);
image.image.resolve(ImageConfiguration.empty).addListener(
ImageStreamListener(
(_, __) { /* You can do something when the image is loaded. */ },
onError: (_, __) {
// Evict the object from the cache to retry to fetch it the next
// time this widget is built.
imageCache.evict(image.image);
},
),
);

虽然这在debug/prod中运行良好,但在我使用HttpOverrides.runZoned()的测试中,客户端总是返回404,测试总是失败,并出现未捕获的NetworkImageLoadException。

修复方法是在测试开始时侦听FlutterError,并且只有在捕获的异常不是NetworkImageLoadException时才抛出。

WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
if (details.exception is! NetworkImageLoadException) throw details.exception;
};

您可以将ErrorBuilder用于

Image.network('Your image url...',
errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
return Text('Error');
},
),

从这里查找文档

我还尝试了cached_network_image包,并尝试了catch。但我找不到解决办法。然后我做了一个基本的实现。我有小图片,所以这个解决方案目前对我有效。

import 'package:http/http.dart' as http;
Map<String, Image?> imageDict = {};
String name;
String? profilepiclink;
Future<Image?> fetchImage() async {
if (imageDict[name] != null) {
return imageDict[name];
} else {
final response = await http.get(Uri.parse(profilepiclink!));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
Image pic = Image.memory(response.bodyBytes);
imageDict[name] = pic;
return pic;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
return null;
}
}
}
Future<Widget> _displayProfilePic() async {
if (profilepiclink != null) {
Image? profilPic = await fetchImage();
return Container(
width: 30,
height: 30,
clipBehavior: Clip.hardEdge,
child: profilPic ?? const Icon(Icons.person),
decoration: const BoxDecoration(shape: BoxShape.circle));
}
return const SizedBox(width: 30, child: Icon(Icons.person));
}
var image = FutureBuilder<Widget>(
future: _displayProfilePic(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return snapshot.data!;
}
return const Icon(Icons.person);
})

包中:flutter/src/paining/network_image_io.dart


if (response.statusCode != HttpStatus.ok) {
// The network may be only temporarily unavailable, or the file will be
// added on the server later. Avoid having future calls to resolve
// fail to check the network again.
await response.drain<List<int>>();
throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
}  

这句话引起了异常。

网络可能只是暂时不可用,或者稍后会将文件添加到服务器上避免以后的呼叫无法再次检查网络

相关内容

  • 没有找到相关文章

最新更新