当前位置: 首页 > 知识库问答 >
问题:

flutter - 如何修改NetworkImage的Headers?

澹台星剑
2024-06-06

如果设置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个答案

季俭
2024-06-06

不限于某种语言提供给库使用者进行配置的方法(这是我能想到的):

  1. 方法的参数中
  2. 提供接口 interface 只要实现接口的中方法就可以覆盖默认的方法
  3. 继承重写
  4. 提供类似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)})';}
 类似资料:
  • 问题内容: 标题说明了一切。我在 SWIFT_MODULE_NAME 的构建设置中进行了 搜索 ,但没有发现任何问题。我也在网上搜索过,并且有对该名称的引用,但没有有关其定义的信息。 此外,我在Apple Docs中找不到任何提及SWIFT_MODULE_NAME的信息。 我确实知道这一点:它在“ Objective-C生成的接口头名称”构建设置中使用,并且可以通过双击设置值来查看: $(SWIF

  • 在我的Nativescript Angular 2 Typescript应用程序中,我希望有一个Nativescript加载任何包含html文本输入字段的远程网站(不受我控制)。 然后我想用我的NativeScript应用程序的值填充这些输入字段。 我以前在android studio中使用java完成过这项工作,在那里可以运行一些JS并修改webview的dom。但是,在没有运行特定于andro

  • 我想向jsonObject添加一个新字段,这个新字段的名称将基于另一个字段的值。明确地说,这是我想要实现的一个例子。 我想为每个json对象添加一个新的字段,它将以字段“stat”的值作为名称。 我尝试使用JsonPath库执行以下操作,但对我来说,这是一个难看的解决方案,因为我将解析json三次,并进行一些手动替换。 这是得到的结果 有没有更好的方法来达到这个结果呢?我试着用gson来做,但它不

  • 我试图为一个使用蓝牙进行通信的应用程序启动一个flutter项目。为此,我使用了flutter blue。 不幸的是,当尝试(在Android设备上)运行我创建的第一个示例时,遇到了以下错误: 如果我在Android Studio上,我会知道如何升级Android minSdkVersion,但在一个扑朔迷离的项目(使用VSCode)上,我有点迷失了。 是否有可能用颤振来增加最小Sdk版本,以及如

  • 问题内容: 我试图对Java Html Document进行一些改进,但是我遇到了与之相关的问题。一件事是,如果用户代理是Java VM,则某些服务器会阻止请求。另一个问题是不会设置或标头字段。由于多个站点使用这些字段来验证是否从其自己的站点访问了内容,因此在此也将我屏蔽了。据我所知,唯一的解决方案是替换HTTP协议的URL处理程序。还是有任何方法可以修改默认的HTTP处理程序? 问题答案: 打开

  • 每当我尝试从终端运行任何应用程序或flutter命令时,我都会遇到问题,显示: