Skip to content

Instantly share code, notes, and snippets.

@jaysonss
Created October 2, 2019 10:50
Show Gist options
  • Save jaysonss/a3278663ed2f3fef47dd2c8fde4ea58d to your computer and use it in GitHub Desktop.
Save jaysonss/a3278663ed2f3fef47dd2c8fde4ea58d to your computer and use it in GitHub Desktop.
添加错误回调的Image
class ImageDemo extends StatefulWidget {
@override
_ImageDemoState createState() => _ImageDemoState();
}
class _ImageDemoState extends State<ImageDemo> {
bool _err = false;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text(
"ImageDemo",
style: TextStyle(fontSize: 17, color: Colors.black87),
),
bottom: PreferredSize(
child: Divider(
height: 1,
),
preferredSize: Size(MediaQuery.of(context).size.width, 1),
),
),
body: Center(
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(color: Colors.black45),
child: _err
? Center(
child: Text("error widget"),
)
: Image(
image: NetworkImageSSL(
"$_kImageUrl",
imageErrorListener: (ex, stack) {
setState(() {
_err = true;
});
},
),
),
),
));
}
}
class NetworkImageSSL extends ImageProvider<NetworkImageSSL> {
const NetworkImageSSL(this.url,
{this.scale = 1.0, this.headers, this.imageErrorListener})
: assert(url != null),
assert(scale != null);
final String url;
final double scale;
final Map<String, String> headers;
final ImageErrorListener imageErrorListener;
@override
Future<NetworkImageSSL> obtainKey(ImageConfiguration configuration) {
return new SynchronousFuture<NetworkImageSSL>(this);
}
@override
ImageStreamCompleter load(NetworkImageSSL key) {
var multiFrameImageStreamCompleter = new MultiFrameImageStreamCompleter(
codec: _loadAsync(key),
scale: key.scale,
informationCollector: () {
List<DiagnosticsNode> informationCollector;
informationCollector.add(DiagnosticsProperty('Image provider', this));
informationCollector.add(DiagnosticsProperty('Image key', key));
return informationCollector;
});
///添加Error Callback
ImageStreamListener listener;
listener = ImageStreamListener((imageInfo, ret) {
multiFrameImageStreamCompleter.removeListener(listener);
}, onError: (ex, stack) {
multiFrameImageStreamCompleter.removeListener(listener);
imageErrorListener?.call(ex, stack);
});
multiFrameImageStreamCompleter.addListener(listener);
return multiFrameImageStreamCompleter;
}
static final HttpClient _httpClient = new HttpClient()
..badCertificateCallback = ((X509Certificate cert, String host, int port) {
///add https certificate check
return true;
});
Future<ui.Codec> _loadAsync(NetworkImageSSL key) async {
assert(key == this);
final Uri resolved = Uri.base.resolve(key.url);
final HttpClientRequest request = await _httpClient.getUrl(resolved);
headers?.forEach((String name, String value) {
request.headers.add(name, value);
});
final HttpClientResponse response = await request.close();
if (response.statusCode != HttpStatus.ok) {
throw new Exception(
'HTTP request failed, statusCode: ${response?.statusCode}, $resolved');
}
final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
if (bytes.lengthInBytes == 0) {
throw new Exception('NetworkImageSSL is an empty file: $resolved');
}
return await ui.instantiateImageCodec(bytes);
}
@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType) return false;
final NetworkImageSSL typedOther = other;
return url == typedOther.url && scale == typedOther.scale;
}
@override
int get hashCode => hashValues(url, scale);
@override
String toString() => '$runtimeType("$url", scale: $scale)';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment