如何修改NetworkImage的Headers?
如果设置Headers只会添加新的UA,原来的UA('dart:io')不会被删除
FadeInImage(
placeholder: MemoryImage(kTransparentImage),
image: NetworkImage(
playlist.coverImgUrl,
headers: {
'User-Agent':
'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BLA-AL00 Build/HUAWEIBLA-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/8.9 Mobile Safari/537.36',
},
),
fadeInDuration: const Duration(milliseconds: 300),
fit: BoxFit.cover,
)
部分NetworkImage源码(headers只会被添加但原来的不会被删除):
Future<ui.Codec> _loadAsync(
NetworkImage key,
StreamController<ImageChunkEvent> chunkEvents, {
required _SimpleDecoderCallback decode,
}) async {
try {
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) {
// 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>>(<int>[]);
throw image_provider.NetworkImageLoadException(statusCode: response.statusCode, uri: resolved);
}
回复
1个回答
test
2024-06-18
不限于某种语言提供给库使用者进行配置的方法(这是我能想到的):
- 方法的参数中
- 提供接口 interface 只要实现接口的中方法就可以覆盖默认的方法
- 继承重写
- 提供类似AOP的方法
既然想删除一些内容那就继承后实现自己业务,功能和NetWorkImage一样;也就是说里面内容是从flutter3.19.5/packages/flutter/lib/src/painting/_network_image_io.dart这里抄的
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
typedef _SimpleDecoderCallback = Future<ui.Codec> Function(
ui.ImmutableBuffer buffer);
class SteNetworkImage extends ImageProvider<NetworkImage>
implements NetworkImage {
/// Creates an object that fetches the image at the given URL.
const SteNetworkImage(this.url, {this.scale = 1.0, this.headers});
@override
final String url;
@override
final double scale;
@override
final Map<String, String>? headers;
@override
Future<NetworkImage> obtainKey(ImageConfiguration configuration) {
return SynchronousFuture<NetworkImage>(this);
}
@override
ImageStreamCompleter loadBuffer(
NetworkImage key, DecoderBufferCallback decode) {
// Ownership of this controller is handed off to [_loadAsync]; it is that
// method's responsibility to close the controller's stream when the image
// has been loaded or an error is thrown.
final StreamController<ImageChunkEvent> chunkEvents =
StreamController<ImageChunkEvent>();
return MultiFrameImageStreamCompleter(
codec: _loadAsync(key as NetworkImage, chunkEvents, decode: decode),
chunkEvents: chunkEvents.stream,
scale: key.scale,
debugLabel: key.url,
informationCollector: () => <DiagnosticsNode>[
DiagnosticsProperty<ImageProvider>('Image provider', this),
DiagnosticsProperty<NetworkImage>('Image key', key),
],
);
}
@override
ImageStreamCompleter loadImage(
NetworkImage key, ImageDecoderCallback decode) {
// Ownership of this controller is handed off to [_loadAsync]; it is that
// method's responsibility to close the controller's stream when the image
// has been loaded or an error is thrown.
final StreamController<ImageChunkEvent> chunkEvents =
StreamController<ImageChunkEvent>();
return MultiFrameImageStreamCompleter(
codec: _loadAsync(key as NetworkImage, chunkEvents, decode: decode),
chunkEvents: chunkEvents.stream,
scale: key.scale,
debugLabel: key.url,
informationCollector: () => <DiagnosticsNode>[
DiagnosticsProperty<ImageProvider>('Image provider', this),
DiagnosticsProperty<NetworkImage>('Image key', key),
],
);
}
// Do not access this field directly; use [_httpClient] instead.
// We set `autoUncompress` to false to ensure that we can trust the value of
// the `Content-Length` HTTP header. We automatically uncompress the content
// in our call to [consolidateHttpClientResponseBytes].
static final HttpClient _sharedHttpClient = HttpClient()
..autoUncompress = false;
static HttpClient get _httpClient {
HttpClient? client;
assert(() {
if (debugNetworkImageHttpClientProvider != null) {
client = debugNetworkImageHttpClientProvider!();
}
return true;
}());
return client ?? _sharedHttpClient;
}
Future<ui.Codec> _loadAsync(
NetworkImage key,
StreamController<ImageChunkEvent> chunkEvents, {
required _SimpleDecoderCallback decode,
}) async {
try {
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) {
// 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>>(<int>[]);
throw NetworkImageLoadException(
statusCode: response.statusCode, uri: resolved);
}
final Uint8List bytes = await consolidateHttpClientResponseBytes(
response,
onBytesReceived: (int cumulative, int? total) {
chunkEvents.add(ImageChunkEvent(
cumulativeBytesLoaded: cumulative,
expectedTotalBytes: total,
));
},
);
if (bytes.lengthInBytes == 0) {
throw Exception('SteNetworkImage is an empty file: $resolved');
}
return decode(await ui.ImmutableBuffer.fromUint8List(bytes));
} catch (e) {
// Depending on where the exception was thrown, the image cache may not
// have had a chance to track the key in the cache at all.
// Schedule a microtask to give the cache a chance to add the key.
scheduleMicrotask(() {
PaintingBinding.instance.imageCache.evict(key);
});
rethrow;
} finally {
chunkEvents.close();
}
}
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType) {
return false;
}
return other is NetworkImage && other.url == url && other.scale == scale;
}
@override
int get hashCode => Object.hash(url, scale);
@override
String toString() =>
'${objectRuntimeType(this, 'SteNetworkImage')}("$url", scale: ${scale.toStringAsFixed(1)})';
}
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容