Baseflow / flutter_cached_network_image

Download, cache and show images in a flutter app
https://baseflow.com
2.41k stars 639 forks source link

How to custom CachedNetworkImageProvider? #481

Open devilWwj opened 3 years ago

devilWwj commented 3 years ago

I want to achieve through inheritance CachedNetworkImageProvider business requirements, but in version 2.2.0, its constructor into the factory method like that:

image

image

renefloor commented 3 years ago

There are now 2 implementations of the ImageProvider. One for web and one for everything else. The ImageProvider was also never really meant to be extendable. What is it that you want to achieve with that?

devilWwj commented 3 years ago

There are now 2 implementations of the ImageProvider. One for web and one for everything else. The ImageProvider was also never really meant to be extendable. What is it that you want to achieve with that?

I need to compress the cache according to the image size. like that:

class EduCachedNetworkImageProvider extends CachedNetworkImageProvider {
  const EduCachedNetworkImageProvider(String url,
      {double scale: 1.0,
      ErrorListener errorListener,
      Map<String, String> headers,
      BaseCacheManager cacheManager,
      })
      : super(url,
            scale: scale,
            errorListener: errorListener,
            headers: headers,
            cacheManager: cacheManager);

  @override
  ImageStreamCompleter load(
      CachedNetworkImageProvider key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key),
      scale: key.scale,
      informationCollector: () sync* {
        yield DiagnosticsProperty<ImageProvider>(
          'Image provider: $this \n Image key: $key',
          this,
          style: DiagnosticsTreeStyle.errorProperty,
        );
      },
    );
  }

  Future<ui.Codec> _loadAsync(CachedNetworkImageProvider key) async {
    var mngr = super.cacheManager ?? DefaultCacheManager();
    try {
      var file = await mngr.getSingleFile(url, headers: super.headers);
      if (file == null) {
        if (super.errorListener != null) super.errorListener();
        return Future<ui.Codec>.error("Couldn't download or retrieve file.");
      }
      return await _loadAsyncFromFile(key, file);
    } catch (error) {

    }
  }

  Future<ui.Codec> _loadAsyncFromFile(
      CachedNetworkImageProvider key, File file) async {
    assert(key == this);

    final Uint8List bytes = await file.readAsBytes();

    if (bytes.lengthInBytes == 0) {
      if (super.errorListener != null) super.errorListener();
      throw Exception("File was empty");
    }

    Uint8List resizedBytes = bytes;
    if (AppUtil.imageMaxSize != null &&
        AppUtil.imageMaxSize > 0 &&
        bytes.length > AppUtil.imageMaxSize) {
      Map<String, dynamic> param = Map();
      param['bytes'] = bytes;
      param['path'] = file.path;
      resizedBytes = await compute(_compressImageQuality, param);
    }

    return await ui.instantiateImageCodec(resizedBytes);
  }

  static Uint8List _compressImageQuality(Map<String, dynamic> param) {
    Uint8List bytes = param['bytes'];
    String path = param['path'];
    if (AppUtil.imageMaxSize > 0 && bytes.length > AppUtil.imageMaxSize) {
      String n = path.toLowerCase();
      Uint8List resizedBytes = Uint8List(0);
      if (n.endsWith('.jpg') || n.endsWith('.jpeg') || n.endsWith('.png')) {
        final image = decodeImage(bytes);
        if (image.width <= AppUtil.imageCompressWidth &&
            image.height <= AppUtil.imageCompressHeigh) {
          return bytes;
        }
        var resized;
        if (image.width > image.height) {
          resized = copyResize(image, width: AppUtil.imageCompressWidth);
        } else {
          resized = copyResize(image, height: AppUtil.imageCompressHeigh);
        }
        if (n.endsWith('.jpg') || n.endsWith('.jpeg')) {
          resizedBytes = encodeJpg(resized,
              quality: ((AppUtil.imageCompressQs ?? 1.0) * 100).round());
        } else {
          resizedBytes = encodePng(resized, level: 2);
        }
        File(path)..writeAsBytes(resizedBytes);
      } else {
        resizedBytes = bytes;
      }
      return resizedBytes;
    } else {
      return bytes;
    }
  }
}
renefloor commented 3 years ago

But that looks like a complete new ImageProvider. You can just extend ImageProvider here. What is the benefit of extending CachedNetworkImageProvider?