返回

Flutter 图片加载源码解析之 ResizeImage、NetworkImage 详尽解析

前端

ResizeImage源码解析

class ResizeImage extends ImageProvider<ResizeImage> {
  ResizeImage(ImageProvider provider, this.targetWidth, this.targetHeight)
      : super(provider);

  final int targetWidth;
  final int targetHeight;

  @override
  ImageStreamCompleter load(ImageConfiguration configuration) {
    return provider.load(configuration).then((ImageStreamCompleter upstream) {
      return MultiFrameImageStreamCompleter(
        codec: _loadAsync(upstream, configuration),
        scale: configuration.devicePixelRatio,
        informationCollector: configuration.informationCollector,
      );
    });
  }

  Future<Codec> _loadAsync(
      ImageStreamCompleter upstream, ImageConfiguration configuration) async {
    final Codec upstreamCodec = await upstream.codec;
    final double pixelRatio = configuration.devicePixelRatio;
    final int finalWidth =
        (targetWidth * pixelRatio).round() ~/ configuration.size.width;
    final int finalHeight =
        (targetHeight * pixelRatio).round() ~/ configuration.size.height;
    return upstreamCodec.getNextFrame(finalWidth, finalHeight);
  }

  @override
  bool operator ==(Object other) {
    if (other is ResizeImage)
      return provider == other.provider &&
          targetWidth == other.targetWidth &&
          targetHeight == other.targetHeight;
    return false;
  }

  @override
  int get hashCode => hashValues(provider.hashCode, targetWidth, targetHeight);
}

ResizeImage源码分析:

  1. ResizeImage构造函数接收两个参数:ImageProvider provider和两个int类型的targetWidth和targetHeight。
  2. ResizeImage的load方法返回一个新的ImageStreamCompleter对象,该对象负责加载和管理ImageProvider对象中图像的数据。
  3. _loadAsync方法接收两个参数:ImageStreamCompleter upstream和ImageConfiguration configuration。
  4. _loadAsync方法首先调用upstreamCodec.getNextFrame方法获取原始图像的Codec对象。
  5. 然后根据configuration中的设备像素比和目标宽高计算出最终图像的宽高。
  6. 最后调用upstreamCodec.getNextFrame方法获取最终图像的Codec对象。

NetworkImage源码解析

class NetworkImage extends ImageProvider<NetworkImage> {
  NetworkImage(this.url, {this.scale = 1.0}) : super();

  final String url;
  final double scale;

  @override
  Future<NetworkImageCompleter> load(ImageConfiguration configuration) async {
    final Uri resolved = Uri.base.resolve(url);
    return await NetworkImageCompleter.load(resolved, scale: scale);
  }

  @override
  bool operator ==(Object other) {
    if (other is NetworkImage)
      return url == other.url && scale == other.scale;
    return false;
  }

  @override
  int get hashCode => hashValues(url, scale);
}

NetworkImage源码分析:

  1. NetworkImage构造函数接收两个参数:String类型的url和double类型的scale。
  2. NetworkImage的load方法返回一个新的NetworkImageCompleter对象,该对象负责加载和管理url中图像的数据。
  3. NetworkImageCompleter.load方法接收两个参数:Uri resolved和double scale。
  4. NetworkImageCompleter.load方法首先解析url,然后根据scale参数加载图像的数据。
  5. 最后返回一个新的NetworkImageCompleter对象。