_network_image_web.dart 3.7 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5

6 7 8 9 10 11 12 13
import 'dart:async';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';

import 'image_provider.dart' as image_provider;
import 'image_stream.dart';

14
/// The dart:html implementation of [image_provider.NetworkImage].
15 16
///
/// NetworkImage on the web does not support decoding to a specified size.
17
@immutable
18 19 20
class NetworkImage
    extends image_provider.ImageProvider<image_provider.NetworkImage>
    implements image_provider.NetworkImage {
21 22 23 24 25 26 27 28 29 30 31 32 33 34
  /// Creates an object that fetches the image at the given URL.
  ///
  /// The arguments [url] and [scale] must not be null.
  const NetworkImage(this.url, {this.scale = 1.0, this.headers})
      : assert(url != null),
        assert(scale != null);

  @override
  final String url;

  @override
  final double scale;

  @override
35
  final Map<String, String>? headers;
36 37

  @override
38 39
  Future<NetworkImage> obtainKey(
      image_provider.ImageConfiguration configuration) {
40 41 42 43
    return SynchronousFuture<NetworkImage>(this);
  }

  @override
44 45 46 47 48 49 50 51
  ImageStreamCompleter load(
      image_provider.NetworkImage key, image_provider.DecoderCallback 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>();

52
    return MultiFrameImageStreamCompleter(
53 54 55
        chunkEvents: chunkEvents.stream,
        codec: _loadAsync(key as NetworkImage, decode, chunkEvents),
        scale: key.scale,
56
        debugLabel: key.url,
57 58 59
        informationCollector: _imageStreamInformationCollector(key));
  }

60
  InformationCollector? _imageStreamInformationCollector(
61
      image_provider.NetworkImage key) {
62
    InformationCollector? collector;
63 64
    assert(() {
      collector = () {
65
        return <DiagnosticsNode>[
66 67
          DiagnosticsProperty<image_provider.ImageProvider>(
              'Image provider', this),
68
          DiagnosticsProperty<NetworkImage>('Image key', key as NetworkImage),
69
        ];
70 71 72 73
      };
      return true;
    }());
    return collector;
74 75
  }

76 77 78 79 80 81
  // TODO(garyq): We should eventually support custom decoding of network images on Web as
  // well, see https://github.com/flutter/flutter/issues/42789.
  //
  // Web does not support decoding network images to a specified size. The decode parameter
  // here is ignored and the web-only `ui.webOnlyInstantiateImageCodecFromUrl` will be used
  // directly in place of the typical `instantiateImageCodec` method.
82 83 84 85
  Future<ui.Codec> _loadAsync(
      NetworkImage key,
      image_provider.DecoderCallback decode,
      StreamController<ImageChunkEvent> chunkEvents) {
86 87 88 89 90
    assert(key == this);

    final Uri resolved = Uri.base.resolve(key.url);
    // This API only exists in the web engine implementation and is not
    // contained in the analyzer summary for Flutter.
91 92 93 94 95
    return ui.webOnlyInstantiateImageCodecFromUrl(resolved, // ignore: undefined_function
        chunkCallback: (int bytes, int total) {
      chunkEvents.add(ImageChunkEvent(
          cumulativeBytesLoaded: bytes, expectedTotalBytes: total));
    }) as Future<ui.Codec>; // ignore: undefined_function
96 97 98
  }

  @override
99
  bool operator ==(Object other) {
100 101 102
    if (other.runtimeType != runtimeType) {
      return false;
    }
103
    return other is NetworkImage && other.url == url && other.scale == scale;
104 105 106 107 108 109
  }

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

  @override
110 111
  String toString() =>
      '${objectRuntimeType(this, 'NetworkImage')}("$url", scale: $scale)';
112
}