From 44e228eb9e292d1374ce03381e9e3d2c968cf002 Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Thu, 7 Dec 2017 14:53:08 -0800 Subject: [PATCH] Move image logic from services/ to painting/. (#13409) This allows the scheduler library to depend on the services library and the painting library to depend on the scheduler library without the services library having to depend on the scheduler library. While I was at it I also cleaned up some of the binding logic: the licenses logic can now be overridden (and the test library does so), and the image cache can now be overridden as well. --- dev/manual_tests/test/mock_image_http.dart | 2 +- packages/flutter/lib/painting.dart | 8 ++- packages/flutter/lib/rendering.dart | 25 ++++---- packages/flutter/lib/services.dart | 5 -- .../flutter/lib/src/foundation/binding.dart | 28 ++++----- .../lib/src/material/circle_avatar.dart | 1 - packages/flutter/lib/src/material/switch.dart | 1 - .../flutter/lib/src/painting/binding.dart | 61 +++++++++++++++++++ .../lib/src/painting/box_decoration.dart | 4 +- .../flutter/lib/src/painting/decoration.dart | 4 +- .../{images.dart => decoration_image.dart} | 3 +- .../lib/src/painting/flutter_logo.dart | 2 +- .../{services => painting}/image_cache.dart | 6 -- .../{services => painting}/image_decoder.dart | 0 .../image_provider.dart | 7 +-- .../image_resolution.dart | 2 +- .../{services => painting}/image_stream.dart | 0 .../lib/src/painting/shape_decoration.dart | 4 +- .../flutter/lib/src/rendering/binding.dart | 4 +- .../flutter/lib/src/rendering/proxy_box.dart | 1 - .../flutter/lib/src/services/binding.dart | 37 ++++++++--- packages/flutter/lib/src/widgets/binding.dart | 2 +- packages/flutter/lib/src/widgets/image.dart | 12 ++-- .../flutter/lib/src/widgets/image_icon.dart | 1 - .../test/cupertino/bottom_tab_bar_test.dart | 2 +- .../flutter/test/cupertino/scaffold_test.dart | 2 +- .../test/cupertino/tab_scaffold_test.dart | 2 +- .../foundation/service_extensions_test.dart | 5 +- .../test/painting/decoration_test.dart | 8 ++- .../{services => painting}/fake_codec.dart | 0 .../fake_image_provider.dart | 2 +- .../image_cache_resize_test.dart | 7 ++- .../image_cache_test.dart | 5 +- .../{services => painting}/image_data.dart | 0 .../image_decoder_test.dart | 2 +- .../image_provider_test.dart | 2 +- .../image_stream_test.dart | 3 +- .../image_test_utils.dart | 2 +- .../mocks_for_image_cache.dart | 2 +- .../test/painting/shape_decoration_test.dart | 4 +- .../test/rendering/rendering_tester.dart | 2 +- .../test/services/asset_bundle_test.dart | 1 + .../test/widgets/fade_in_image_test.dart | 2 +- .../test/widgets/image_headers_test.dart | 2 +- .../flutter/test/widgets/image_icon_test.dart | 3 +- .../widgets/image_package_asset_test.dart | 1 - .../flutter/test/widgets/image_rtl_test.dart | 1 - packages/flutter/test/widgets/image_test.dart | 3 +- .../test/widgets/obscured_animated_image.dart | 6 +- .../lib/src/extension/extension.dart | 2 +- packages/flutter_test/lib/src/binding.dart | 9 ++- 51 files changed, 193 insertions(+), 107 deletions(-) create mode 100644 packages/flutter/lib/src/painting/binding.dart rename packages/flutter/lib/src/painting/{images.dart => decoration_image.dart} (99%) rename packages/flutter/lib/src/{services => painting}/image_cache.dart (94%) rename packages/flutter/lib/src/{services => painting}/image_decoder.dart (100%) rename packages/flutter/lib/src/{services => painting}/image_provider.dart (99%) rename packages/flutter/lib/src/{services => painting}/image_resolution.dart (99%) rename packages/flutter/lib/src/{services => painting}/image_stream.dart (100%) rename packages/flutter/test/{services => painting}/fake_codec.dart (100%) rename packages/flutter/test/{services => painting}/fake_image_provider.dart (96%) rename packages/flutter/test/{services => painting}/image_cache_resize_test.dart (88%) rename packages/flutter/test/{services => painting}/image_cache_test.dart (95%) rename packages/flutter/test/{services => painting}/image_data.dart (100%) rename packages/flutter/test/{services => painting}/image_decoder_test.dart (93%) rename packages/flutter/test/{services => painting}/image_provider_test.dart (92%) rename packages/flutter/test/{services => painting}/image_stream_test.dart (99%) rename packages/flutter/test/{services => painting}/image_test_utils.dart (97%) rename packages/flutter/test/{services => painting}/mocks_for_image_cache.dart (97%) diff --git a/dev/manual_tests/test/mock_image_http.dart b/dev/manual_tests/test/mock_image_http.dart index b491bd9a612..2ea12d8e9cb 100644 --- a/dev/manual_tests/test/mock_image_http.dart +++ b/dev/manual_tests/test/mock_image_http.dart @@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart' show ValueGetter; import 'package:http/http.dart' as http; import 'package:http/testing.dart' as http; -import '../../../packages/flutter/test/services/image_data.dart'; +import '../../../packages/flutter/test/painting/image_data.dart'; // Returns a mock HTTP client that responds with an image to all requests. ValueGetter createMockImageHttpClient = () { diff --git a/packages/flutter/lib/painting.dart b/packages/flutter/lib/painting.dart index 031a8a9c4a8..dfae5c5bef0 100644 --- a/packages/flutter/lib/painting.dart +++ b/packages/flutter/lib/painting.dart @@ -19,6 +19,7 @@ library painting; export 'src/painting/alignment.dart'; export 'src/painting/basic_types.dart'; +export 'src/painting/binding.dart'; export 'src/painting/border_radius.dart'; export 'src/painting/borders.dart'; export 'src/painting/box_border.dart'; @@ -28,12 +29,17 @@ export 'src/painting/box_shadow.dart'; export 'src/painting/circle_border.dart'; export 'src/painting/colors.dart'; export 'src/painting/decoration.dart'; +export 'src/painting/decoration_image.dart'; export 'src/painting/edge_insets.dart'; export 'src/painting/flutter_logo.dart'; export 'src/painting/fractional_offset.dart'; export 'src/painting/geometry.dart'; export 'src/painting/gradient.dart'; -export 'src/painting/images.dart'; +export 'src/painting/image_cache.dart'; +export 'src/painting/image_decoder.dart'; +export 'src/painting/image_provider.dart'; +export 'src/painting/image_resolution.dart'; +export 'src/painting/image_stream.dart'; export 'src/painting/matrix_utils.dart'; export 'src/painting/rounded_rectangle_border.dart'; export 'src/painting/shape_decoration.dart'; diff --git a/packages/flutter/lib/rendering.dart b/packages/flutter/lib/rendering.dart index 4e4e97d76a1..979ea124362 100644 --- a/packages/flutter/lib/rendering.dart +++ b/packages/flutter/lib/rendering.dart @@ -6,20 +6,19 @@ /// /// To use, import `package:flutter/rendering.dart`. /// -/// The [RenderObject] hierarchy is used by the Flutter Widgets -/// library to implement its layout and painting back-end. Generally, -/// while you may use custom [RenderBox] classes for specific effects -/// in your applications, most of the time your only interaction with -/// the [RenderObject] hierarchy will be in debugging layout issues. +/// The [RenderObject] hierarchy is used by the Flutter Widgets library to +/// implement its layout and painting back-end. Generally, while you may use +/// custom [RenderBox] classes for specific effects in your applications, most +/// of the time your only interaction with the [RenderObject] hierarchy will be +/// in debugging layout issues. /// -/// If you are developing your own library or application directly on -/// top of the rendering library, then you will want to have a binding -/// (see [BindingBase]). You can use [RenderingFlutterBinding], or you -/// can create your own binding. If you create your own binding, it -/// needs to import at least [SchedulerBinding], [GestureBinding], -/// [ServicesBinding], and [RendererBinding]. The rendering library -/// does not automatically create a binding, but relies on one being -/// initialized with those features. +/// If you are developing your own library or application directly on top of the +/// rendering library, then you will want to have a binding (see [BindingBase]). +/// You can use [RenderingFlutterBinding], or you can create your own binding. +/// If you create your own binding, it needs to import at least +/// [ServicesBinding], [GestureBinding], [SchedulerBinding], [PaintingBinding], +/// and [RendererBinding]. The rendering library does not automatically create a +/// binding, but relies on one being initialized with those features. library rendering; export 'package:flutter/foundation.dart' show diff --git a/packages/flutter/lib/services.dart b/packages/flutter/lib/services.dart index 74e1858e69a..c72fbbc22f4 100644 --- a/packages/flutter/lib/services.dart +++ b/packages/flutter/lib/services.dart @@ -15,11 +15,6 @@ export 'src/services/binding.dart'; export 'src/services/clipboard.dart'; export 'src/services/haptic_feedback.dart'; export 'src/services/http_client.dart'; -export 'src/services/image_cache.dart'; -export 'src/services/image_decoder.dart'; -export 'src/services/image_provider.dart'; -export 'src/services/image_resolution.dart'; -export 'src/services/image_stream.dart'; export 'src/services/message_codec.dart'; export 'src/services/message_codecs.dart'; export 'src/services/platform_channel.dart'; diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart index e0cf406282b..bdaa05fdd6b 100644 --- a/packages/flutter/lib/src/foundation/binding.dart +++ b/packages/flutter/lib/src/foundation/binding.dart @@ -26,19 +26,17 @@ typedef Future> ServiceExtensionCallback(Map /// "bindings"). /// /// To use this class in a mixin, inherit from it and implement -/// [initInstances()]. The mixin is guaranteed to only be constructed -/// once in the lifetime of the app (more precisely, it will assert if -/// constructed twice in checked mode). +/// [initInstances()]. The mixin is guaranteed to only be constructed once in +/// the lifetime of the app (more precisely, it will assert if constructed twice +/// in checked mode). /// -/// The top-most layer used to write the application will have a -/// concrete class that inherits from BindingBase and uses all the -/// various BindingBase mixins (such as [ServicesBinding]). For example, the -/// Widgets library in flutter introduces a binding called -/// [WidgetsFlutterBinding]. The relevant library defines how to create -/// the binding. It could be implied (for example, -/// [WidgetsFlutterBinding] is automatically started from [runApp]), or -/// the application might be required to explicitly call the -/// constructor. +/// The top-most layer used to write the application will have a concrete class +/// that inherits from [BindingBase] and uses all the various [BindingBase] +/// mixins (such as [ServicesBinding]). For example, the Widgets library in +/// Flutter introduces a binding called [WidgetsFlutterBinding]. The relevant +/// library defines how to create the binding. It could be implied (for example, +/// [WidgetsFlutterBinding] is automatically started from [runApp]), or the +/// application might be required to explicitly call the constructor. abstract class BindingBase { /// Default abstract constructor for bindings. /// @@ -106,15 +104,15 @@ abstract class BindingBase { assert(!_debugServiceExtensionsRegistered); registerSignalServiceExtension( name: 'reassemble', - callback: reassembleApplication + callback: reassembleApplication, ); registerSignalServiceExtension( name: 'exit', - callback: _exitApplication + callback: _exitApplication, ); registerSignalServiceExtension( name: 'frameworkPresent', - callback: () => new Future.value() + callback: () => new Future.value(), ); assert(() { registerServiceExtension( diff --git a/packages/flutter/lib/src/material/circle_avatar.dart b/packages/flutter/lib/src/material/circle_avatar.dart index 9bd196ade0d..af9b94cdb29 100644 --- a/packages/flutter/lib/src/material/circle_avatar.dart +++ b/packages/flutter/lib/src/material/circle_avatar.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'colors.dart'; diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index d685ae29df6..35d32f4f9e2 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'colors.dart'; diff --git a/packages/flutter/lib/src/painting/binding.dart b/packages/flutter/lib/src/painting/binding.dart new file mode 100644 index 00000000000..33b6c670851 --- /dev/null +++ b/packages/flutter/lib/src/painting/binding.dart @@ -0,0 +1,61 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart' show ServicesBinding; + +import 'image_cache.dart'; + +/// Binding for the painting library. +/// +/// Hooks into the cache eviction logic to clear the image cache. +/// +/// Requires the [ServicesBinding] to be mixed in earlier. +abstract class PaintingBinding extends BindingBase with ServicesBinding { + // This class is intended to be used as a mixin, and should not be + // extended directly. + factory PaintingBinding._() => null; + + @override + void initInstances() { + super.initInstances(); + _instance = this; + _imageCache = createImageCache(); + } + + /// The current [PaintingBinding], if one has been created. + static PaintingBinding get instance => _instance; + static PaintingBinding _instance; + + /// The singleton that implements the Flutter framework's image cache. + /// + /// The cache is used internally by [ImageProvider] and should generally not + /// be accessed directly. + /// + /// The image cache is created during startup by the [createImageCache] + /// method. + ImageCache get imageCache => _imageCache; + ImageCache _imageCache; + + /// Creates the [ImageCache] singleton (accessible via [imageCache]). + /// + /// This method can be overridden to provide a custom image cache. + @protected + ImageCache createImageCache() => new ImageCache(); + + @override + void evict(String asset) { + super.evict(asset); + imageCache.clear(); + } +} + +/// The singleton that implements the Flutter framework's image cache. +/// +/// The cache is used internally by [ImageProvider] and should generally not be +/// accessed directly. +/// +/// The image cache is created during startup by the [PaintingBinding]'s +/// [PaintingBinding.createImageCache] method. +ImageCache get imageCache => PaintingBinding.instance.imageCache; diff --git a/packages/flutter/lib/src/painting/box_decoration.dart b/packages/flutter/lib/src/painting/box_decoration.dart index 9a401b78de2..43c8a69bd7a 100644 --- a/packages/flutter/lib/src/painting/box_decoration.dart +++ b/packages/flutter/lib/src/painting/box_decoration.dart @@ -5,16 +5,16 @@ import 'dart:math' as math; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'basic_types.dart'; import 'border_radius.dart'; import 'box_border.dart'; import 'box_shadow.dart'; import 'decoration.dart'; +import 'decoration_image.dart'; import 'edge_insets.dart'; import 'gradient.dart'; -import 'images.dart'; +import 'image_provider.dart'; /// An immutable description of how to paint a box. /// diff --git a/packages/flutter/lib/src/painting/decoration.dart b/packages/flutter/lib/src/painting/decoration.dart index 437cda1e004..c8b22ce39dd 100644 --- a/packages/flutter/lib/src/painting/decoration.dart +++ b/packages/flutter/lib/src/painting/decoration.dart @@ -3,12 +3,10 @@ // found in the LICENSE file. import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'basic_types.dart'; import 'edge_insets.dart'; - -export 'package:flutter/services.dart' show ImageConfiguration; +import 'image_provider.dart'; // This group of classes is intended for painting in cartesian coordinates. diff --git a/packages/flutter/lib/src/painting/images.dart b/packages/flutter/lib/src/painting/decoration_image.dart similarity index 99% rename from packages/flutter/lib/src/painting/images.dart rename to packages/flutter/lib/src/painting/decoration_image.dart index 4cf5fb677b9..d0f96f86728 100644 --- a/packages/flutter/lib/src/painting/images.dart +++ b/packages/flutter/lib/src/painting/decoration_image.dart @@ -5,12 +5,13 @@ import 'dart:ui' as ui show Image; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'alignment.dart'; import 'basic_types.dart'; import 'borders.dart'; import 'box_fit.dart'; +import 'image_provider.dart'; +import 'image_stream.dart'; /// How to paint any portions of a box not covered by an image. enum ImageRepeat { diff --git a/packages/flutter/lib/src/painting/flutter_logo.dart b/packages/flutter/lib/src/painting/flutter_logo.dart index a15c62df1bf..9675c4185b2 100644 --- a/packages/flutter/lib/src/painting/flutter_logo.dart +++ b/packages/flutter/lib/src/painting/flutter_logo.dart @@ -6,7 +6,6 @@ import 'dart:math' as math; import 'dart:typed_data'; import 'dart:ui' as ui show Gradient, TextBox, lerpDouble; -import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; import 'alignment.dart'; @@ -14,6 +13,7 @@ import 'basic_types.dart'; import 'box_fit.dart'; import 'decoration.dart'; import 'edge_insets.dart'; +import 'image_provider.dart'; import 'text_painter.dart'; import 'text_span.dart'; import 'text_style.dart'; diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/painting/image_cache.dart similarity index 94% rename from packages/flutter/lib/src/services/image_cache.dart rename to packages/flutter/lib/src/painting/image_cache.dart index 763067f93bb..1de0c03e79e 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/painting/image_cache.dart @@ -89,9 +89,3 @@ class ImageCache { return result; } } - -/// The singleton that implements the Flutter framework's image cache. -/// -/// The cache is used internally by [ImageProvider] and should generally not be -/// accessed directly. -final ImageCache imageCache = new ImageCache(); diff --git a/packages/flutter/lib/src/services/image_decoder.dart b/packages/flutter/lib/src/painting/image_decoder.dart similarity index 100% rename from packages/flutter/lib/src/services/image_decoder.dart rename to packages/flutter/lib/src/painting/image_decoder.dart diff --git a/packages/flutter/lib/src/services/image_provider.dart b/packages/flutter/lib/src/painting/image_provider.dart similarity index 99% rename from packages/flutter/lib/src/services/image_provider.dart rename to packages/flutter/lib/src/painting/image_provider.dart index e78e54bcae0..a91502e1440 100644 --- a/packages/flutter/lib/src/services/image_provider.dart +++ b/packages/flutter/lib/src/painting/image_provider.dart @@ -9,11 +9,10 @@ import 'dart:ui' as ui show instantiateImageCodec, Codec; import 'dart:ui' show Size, Locale, TextDirection, hashValues; import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; -import 'asset_bundle.dart'; -import 'http_client.dart'; -import 'image_cache.dart'; +import 'binding.dart'; import 'image_stream.dart'; /// Configuration information passed to the [ImageProvider.resolve] method to @@ -262,7 +261,7 @@ abstract class ImageProvider { T obtainedKey; obtainKey(configuration).then((T key) { obtainedKey = key; - stream.setCompleter(imageCache.putIfAbsent(key, () => load(key))); + stream.setCompleter(PaintingBinding.instance.imageCache.putIfAbsent(key, () => load(key))); }).catchError( (dynamic exception, StackTrace stack) async { FlutterError.reportError(new FlutterErrorDetails( diff --git a/packages/flutter/lib/src/services/image_resolution.dart b/packages/flutter/lib/src/painting/image_resolution.dart similarity index 99% rename from packages/flutter/lib/src/services/image_resolution.dart rename to packages/flutter/lib/src/painting/image_resolution.dart index d31309ecbda..75c2a15ce08 100644 --- a/packages/flutter/lib/src/services/image_resolution.dart +++ b/packages/flutter/lib/src/painting/image_resolution.dart @@ -8,8 +8,8 @@ import 'dart:convert'; import 'dart:ui' show hashValues; import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; -import 'asset_bundle.dart'; import 'image_provider.dart'; const String _kAssetManifestFileName = 'AssetManifest.json'; diff --git a/packages/flutter/lib/src/services/image_stream.dart b/packages/flutter/lib/src/painting/image_stream.dart similarity index 100% rename from packages/flutter/lib/src/services/image_stream.dart rename to packages/flutter/lib/src/painting/image_stream.dart diff --git a/packages/flutter/lib/src/painting/shape_decoration.dart b/packages/flutter/lib/src/painting/shape_decoration.dart index 9e3d4707ae7..f48c4eaca01 100644 --- a/packages/flutter/lib/src/painting/shape_decoration.dart +++ b/packages/flutter/lib/src/painting/shape_decoration.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'basic_types.dart'; import 'borders.dart'; @@ -12,9 +11,10 @@ import 'box_decoration.dart'; import 'box_shadow.dart'; import 'circle_border.dart'; import 'decoration.dart'; +import 'decoration_image.dart'; import 'edge_insets.dart'; import 'gradient.dart'; -import 'images.dart'; +import 'image_provider.dart'; import 'rounded_rectangle_border.dart'; /// An immutable description of how to paint an arbitrary shape. diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 25640c5a12b..5b9a13710fd 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -20,7 +20,7 @@ import 'view.dart'; export 'package:flutter/gestures.dart' show HitTestResult; /// The glue between the render tree and the Flutter engine. -abstract class RendererBinding extends BindingBase with SchedulerBinding, ServicesBinding, HitTestable { +abstract class RendererBinding extends BindingBase with ServicesBinding, SchedulerBinding, HitTestable { // This class is intended to be used as a mixin, and should not be // extended directly. factory RendererBinding._() => null; @@ -347,7 +347,7 @@ void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) { /// that layer's binding. /// /// See also [BindingBase]. -class RenderingFlutterBinding extends BindingBase with SchedulerBinding, GestureBinding, ServicesBinding, RendererBinding { +class RenderingFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, RendererBinding { /// Creates a binding for the rendering layer. /// /// The `root` render box is attached directly to the [renderView] and is diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 66320f05e9a..e1edd974eba 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -8,7 +8,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/semantics.dart'; -import 'package:flutter/services.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart index 03df4438479..c43af11f184 100644 --- a/packages/flutter/lib/src/services/binding.dart +++ b/packages/flutter/lib/src/services/binding.dart @@ -8,14 +8,14 @@ import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'asset_bundle.dart'; -import 'image_cache.dart'; import 'platform_messages.dart'; /// Listens for platform messages and directs them to [BinaryMessages]. /// -/// The ServicesBinding also registers a [LicenseEntryCollector] that exposes +/// The [ServicesBinding] also registers a [LicenseEntryCollector] that exposes /// the licenses found in the `LICENSE` file stored at the root of the asset -/// bundle. +/// bundle, and implements the `ext.flutter.evict` service extension (see +/// [evict]). abstract class ServicesBinding extends BindingBase { // This class is intended to be used as a mixin, and should not be // extended directly. @@ -26,6 +26,16 @@ abstract class ServicesBinding extends BindingBase { super.initInstances(); ui.window ..onPlatformMessage = BinaryMessages.handlePlatformMessage; + initLicenses(); + } + + /// Adds relevant licenses to the [LicenseRegistry]. + /// + /// By default, the [ServicesBinding]'s implementation of [initLicenses] adds + /// all the licenses collected by the `flutter` tool during compilation. + @protected + @mustCallSuper + void initLicenses() { LicenseRegistry.addLicense(_addLicenses); } @@ -51,16 +61,25 @@ abstract class ServicesBinding extends BindingBase { void initServiceExtensions() { super.initServiceExtensions(); registerStringServiceExtension( - // ext.flutter.evict value=foo.png will cause foo.png to be evicted from the rootBundle cache - // and cause the entire image cache to be cleared. This is used by hot reload mode to clear - // out the cache of resources that have changed. - // TODO(ianh): find a way to only evict affected images, not all images + // ext.flutter.evict value=foo.png will cause foo.png to be evicted from + // the rootBundle cache and cause the entire image cache to be cleared. + // This is used by hot reload mode to clear out the cache of resources + // that have changed. name: 'evict', getter: () async => '', setter: (String value) async { - rootBundle.evict(value); - imageCache.clear(); + evict(value); } ); } + + /// Called in response to the `ext.flutter.evict` service extension. + /// + /// This is used by the `flutter` tool during hot reload so that any images + /// that have changed on disk get cleared from caches. + @protected + @mustCallSuper + void evict(String asset) { + rootBundle.evict(asset); + } } diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index 1f3d3a5d478..95535f11c98 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -891,7 +891,7 @@ class RenderObjectToWidgetElement extends RootRenderObje /// A concrete binding for applications based on the Widgets framework. /// This is the glue that binds the framework to the Flutter engine. -class WidgetsFlutterBinding extends BindingBase with SchedulerBinding, GestureBinding, ServicesBinding, RendererBinding, WidgetsBinding { +class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, RendererBinding, WidgetsBinding { /// Returns an instance of the [WidgetsBinding], creating and /// initializing it if necessary. If one is created, it will be a diff --git a/packages/flutter/lib/src/widgets/image.dart b/packages/flutter/lib/src/widgets/image.dart index 9d278cd3707..bf563d42148 100644 --- a/packages/flutter/lib/src/widgets/image.dart +++ b/packages/flutter/lib/src/widgets/image.dart @@ -7,6 +7,7 @@ import 'dart:io' show File; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; +import 'package:flutter/painting.dart'; import 'package:flutter/services.dart'; import 'basic.dart'; @@ -15,13 +16,16 @@ import 'localizations.dart'; import 'media_query.dart'; import 'ticker_provider.dart'; -export 'package:flutter/services.dart' show - ImageProvider, +export 'package:flutter/painting.dart' show AssetImage, ExactAssetImage, + FileImage, + ImageConfiguration, + ImageInfo, + ImageStream, + ImageProvider, MemoryImage, - NetworkImage, - FileImage; + NetworkImage; /// Creates an [ImageConfiguration] based on the given [BuildContext] (and /// optionally size). diff --git a/packages/flutter/lib/src/widgets/image_icon.dart b/packages/flutter/lib/src/widgets/image_icon.dart index 4b67bd47fcb..18fc7e00236 100644 --- a/packages/flutter/lib/src/widgets/image_icon.dart +++ b/packages/flutter/lib/src/widgets/image_icon.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart index 0396bcecfdd..effa4df395b 100644 --- a/packages/flutter/test/cupertino/bottom_tab_bar_test.dart +++ b/packages/flutter/test/cupertino/bottom_tab_bar_test.dart @@ -5,7 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/mocks_for_image_cache.dart'; +import '../painting/mocks_for_image_cache.dart'; Future pumpWidgetWithBoilerplate(WidgetTester tester, Widget widget) async { await tester.pumpWidget( diff --git a/packages/flutter/test/cupertino/scaffold_test.dart b/packages/flutter/test/cupertino/scaffold_test.dart index ec07a84c92b..a83a3178065 100644 --- a/packages/flutter/test/cupertino/scaffold_test.dart +++ b/packages/flutter/test/cupertino/scaffold_test.dart @@ -5,7 +5,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/mocks_for_image_cache.dart'; +import '../painting/mocks_for_image_cache.dart'; /// Integration tests testing both [CupertinoPageScaffold] and [CupertinoTabScaffold]. void main() { diff --git a/packages/flutter/test/cupertino/tab_scaffold_test.dart b/packages/flutter/test/cupertino/tab_scaffold_test.dart index dcd3c7a49a3..e17cd7f41a2 100644 --- a/packages/flutter/test/cupertino/tab_scaffold_test.dart +++ b/packages/flutter/test/cupertino/tab_scaffold_test.dart @@ -5,8 +5,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../painting/mocks_for_image_cache.dart'; import '../rendering/rendering_tester.dart'; -import '../services/mocks_for_image_cache.dart'; List selectedTabs; diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart index 815b922b846..f9de7501f23 100644 --- a/packages/flutter/test/foundation/service_extensions_test.dart +++ b/packages/flutter/test/foundation/service_extensions_test.dart @@ -16,9 +16,10 @@ import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; class TestServiceExtensionsBinding extends BindingBase - with SchedulerBinding, - ServicesBinding, + with ServicesBinding, GestureBinding, + SchedulerBinding, + PaintingBinding, RendererBinding, WidgetsBinding { diff --git a/packages/flutter/test/painting/decoration_test.dart b/packages/flutter/test/painting/decoration_test.dart index 039f2b8d73e..c4d2314efaf 100644 --- a/packages/flutter/test/painting/decoration_test.dart +++ b/packages/flutter/test/painting/decoration_test.dart @@ -7,11 +7,11 @@ import 'dart:ui' as ui show Image, ColorFilter; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; -import 'package:flutter/services.dart'; import 'package:quiver/testing/async.dart'; - import 'package:test/test.dart'; -import '../services/mocks_for_image_cache.dart'; + +import '../painting/mocks_for_image_cache.dart'; +import '../rendering/rendering_tester.dart'; class TestCanvas implements Canvas { TestCanvas([this.invocations]); @@ -90,6 +90,8 @@ class TestImage extends ui.Image { } void main() { + new TestRenderingFlutterBinding(); // initializes the imageCache + test('Decoration.lerp()', () { final BoxDecoration a = const BoxDecoration(color: const Color(0xFFFFFFFF)); final BoxDecoration b = const BoxDecoration(color: const Color(0x00000000)); diff --git a/packages/flutter/test/services/fake_codec.dart b/packages/flutter/test/painting/fake_codec.dart similarity index 100% rename from packages/flutter/test/services/fake_codec.dart rename to packages/flutter/test/painting/fake_codec.dart diff --git a/packages/flutter/test/services/fake_image_provider.dart b/packages/flutter/test/painting/fake_image_provider.dart similarity index 96% rename from packages/flutter/test/services/fake_image_provider.dart rename to packages/flutter/test/painting/fake_image_provider.dart index 71983c93a30..2a07b9cc25b 100644 --- a/packages/flutter/test/services/fake_image_provider.dart +++ b/packages/flutter/test/painting/fake_image_provider.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'dart:ui' as ui show Codec; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; /// An image provider implementation for testing that is using a [ui.Codec] /// that it was given at construction time (typically the job of real image diff --git a/packages/flutter/test/services/image_cache_resize_test.dart b/packages/flutter/test/painting/image_cache_resize_test.dart similarity index 88% rename from packages/flutter/test/services/image_cache_resize_test.dart rename to packages/flutter/test/painting/image_cache_resize_test.dart index bea76e58e22..802215cbf77 100644 --- a/packages/flutter/test/services/image_cache_resize_test.dart +++ b/packages/flutter/test/painting/image_cache_resize_test.dart @@ -2,13 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; import 'package:test/test.dart'; +import '../rendering/rendering_tester.dart'; import 'mocks_for_image_cache.dart'; void main() { - test('Image cache resizing', () async { + new TestRenderingFlutterBinding(); // initializes the imageCache + +test('Image cache resizing', () async { imageCache.maximumSize = 2; diff --git a/packages/flutter/test/services/image_cache_test.dart b/packages/flutter/test/painting/image_cache_test.dart similarity index 95% rename from packages/flutter/test/services/image_cache_test.dart rename to packages/flutter/test/painting/image_cache_test.dart index 9e0617664e7..82c6744c403 100644 --- a/packages/flutter/test/services/image_cache_test.dart +++ b/packages/flutter/test/painting/image_cache_test.dart @@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; import 'package:test/test.dart'; +import '../rendering/rendering_tester.dart'; import 'mocks_for_image_cache.dart'; void main() { + new TestRenderingFlutterBinding(); // initializes the imageCache + test('Image cache', () async { imageCache.maximumSize = 3; diff --git a/packages/flutter/test/services/image_data.dart b/packages/flutter/test/painting/image_data.dart similarity index 100% rename from packages/flutter/test/services/image_data.dart rename to packages/flutter/test/painting/image_data.dart diff --git a/packages/flutter/test/services/image_decoder_test.dart b/packages/flutter/test/painting/image_decoder_test.dart similarity index 93% rename from packages/flutter/test/services/image_decoder_test.dart rename to packages/flutter/test/painting/image_decoder_test.dart index 28e388af63e..e6937239467 100644 --- a/packages/flutter/test/services/image_decoder_test.dart +++ b/packages/flutter/test/painting/image_decoder_test.dart @@ -5,7 +5,7 @@ import 'dart:typed_data'; import 'dart:ui' as ui; -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; import 'package:test/test.dart'; import 'image_data.dart'; diff --git a/packages/flutter/test/services/image_provider_test.dart b/packages/flutter/test/painting/image_provider_test.dart similarity index 92% rename from packages/flutter/test/services/image_provider_test.dart rename to packages/flutter/test/painting/image_provider_test.dart index 08512356a4d..1513da093fc 100644 --- a/packages/flutter/test/services/image_provider_test.dart +++ b/packages/flutter/test/painting/image_provider_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { diff --git a/packages/flutter/test/services/image_stream_test.dart b/packages/flutter/test/painting/image_stream_test.dart similarity index 99% rename from packages/flutter/test/services/image_stream_test.dart rename to packages/flutter/test/painting/image_stream_test.dart index 331d78b0735..46bdd9afc12 100644 --- a/packages/flutter/test/services/image_stream_test.dart +++ b/packages/flutter/test/painting/image_stream_test.dart @@ -4,8 +4,9 @@ import 'dart:async'; import 'dart:ui'; + +import 'package:flutter/painting.dart'; import 'package:flutter/scheduler.dart' show timeDilation; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; class FakeFrameInfo extends FrameInfo { diff --git a/packages/flutter/test/services/image_test_utils.dart b/packages/flutter/test/painting/image_test_utils.dart similarity index 97% rename from packages/flutter/test/services/image_test_utils.dart rename to packages/flutter/test/painting/image_test_utils.dart index 170f2662073..8a8b5311e0a 100644 --- a/packages/flutter/test/services/image_test_utils.dart +++ b/packages/flutter/test/painting/image_test_utils.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; import 'image_data.dart'; diff --git a/packages/flutter/test/services/mocks_for_image_cache.dart b/packages/flutter/test/painting/mocks_for_image_cache.dart similarity index 97% rename from packages/flutter/test/services/mocks_for_image_cache.dart rename to packages/flutter/test/painting/mocks_for_image_cache.dart index 5623fdb739e..b910a8e24a7 100644 --- a/packages/flutter/test/services/mocks_for_image_cache.dart +++ b/packages/flutter/test/painting/mocks_for_image_cache.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'dart:ui' as ui show Image; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; class TestImageInfo implements ImageInfo { const TestImageInfo(this.value, { this.image, this.scale }); diff --git a/packages/flutter/test/painting/shape_decoration_test.dart b/packages/flutter/test/painting/shape_decoration_test.dart index ba8613d39bd..bcc8ae5933c 100644 --- a/packages/flutter/test/painting/shape_decoration_test.dart +++ b/packages/flutter/test/painting/shape_decoration_test.dart @@ -6,12 +6,14 @@ import 'dart:ui' as ui; import 'package:flutter/foundation.dart'; import 'package:flutter/painting.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import '../rendering/mock_canvas.dart'; +import '../rendering/rendering_tester.dart'; void main() { + new TestRenderingFlutterBinding(); // initializes the imageCache + test('ShapeDecoration constructor', () { final Color colorR = const Color(0xffff0000); final Color colorG = const Color(0xff00ff00); diff --git a/packages/flutter/test/rendering/rendering_tester.dart b/packages/flutter/test/rendering/rendering_tester.dart index 8f778c22d5d..bbd79d49b0a 100644 --- a/packages/flutter/test/rendering/rendering_tester.dart +++ b/packages/flutter/test/rendering/rendering_tester.dart @@ -11,7 +11,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart' show EnginePhase; export 'package:flutter_test/flutter_test.dart' show EnginePhase; -class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, RendererBinding, GestureBinding { +class TestRenderingFlutterBinding extends BindingBase with ServicesBinding, GestureBinding, SchedulerBinding, PaintingBinding, RendererBinding { EnginePhase phase = EnginePhase.composite; @override diff --git a/packages/flutter/test/services/asset_bundle_test.dart b/packages/flutter/test/services/asset_bundle_test.dart index 8ca6313f767..9be659004e2 100644 --- a/packages/flutter/test/services/asset_bundle_test.dart +++ b/packages/flutter/test/services/asset_bundle_test.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; +import 'package:flutter/painting.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/packages/flutter/test/widgets/fade_in_image_test.dart b/packages/flutter/test/widgets/fade_in_image_test.dart index 61bf99a8e28..63cfa8dcec1 100644 --- a/packages/flutter/test/widgets/fade_in_image_test.dart +++ b/packages/flutter/test/widgets/fade_in_image_test.dart @@ -7,7 +7,7 @@ import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/image_test_utils.dart'; +import '../painting/image_test_utils.dart'; Future main() async { // These must run outside test zone to complete diff --git a/packages/flutter/test/widgets/image_headers_test.dart b/packages/flutter/test/widgets/image_headers_test.dart index b10f69cbb09..c6f62954aad 100644 --- a/packages/flutter/test/widgets/image_headers_test.dart +++ b/packages/flutter/test/widgets/image_headers_test.dart @@ -10,7 +10,7 @@ import 'package:http/http.dart' as http; import 'package:http/testing.dart' as http; import 'package:flutter/services.dart' show createHttpClient; -import '../services/image_data.dart'; +import '../painting/image_data.dart'; void main() { testWidgets('Headers', (WidgetTester tester) async { diff --git a/packages/flutter/test/widgets/image_icon_test.dart b/packages/flutter/test/widgets/image_icon_test.dart index 8212083ac0d..c581716cdcb 100644 --- a/packages/flutter/test/widgets/image_icon_test.dart +++ b/packages/flutter/test/widgets/image_icon_test.dart @@ -3,11 +3,10 @@ // found in the LICENSE file. import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/mocks_for_image_cache.dart'; +import '../painting/mocks_for_image_cache.dart'; const ImageProvider _kImage = const TestImageProvider(21, 42); diff --git a/packages/flutter/test/widgets/image_package_asset_test.dart b/packages/flutter/test/widgets/image_package_asset_test.dart index e27ba92cbac..15f26102ce3 100644 --- a/packages/flutter/test/widgets/image_package_asset_test.dart +++ b/packages/flutter/test/widgets/image_package_asset_test.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/packages/flutter/test/widgets/image_rtl_test.dart b/packages/flutter/test/widgets/image_rtl_test.dart index 6403a7ab0da..522616bda17 100644 --- a/packages/flutter/test/widgets/image_rtl_test.dart +++ b/packages/flutter/test/widgets/image_rtl_test.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:ui' as ui show Image; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart index af4216d8de1..05ae19d9021 100644 --- a/packages/flutter/test/widgets/image_test.dart +++ b/packages/flutter/test/widgets/image_test.dart @@ -8,11 +8,10 @@ import 'dart:ui' as ui show Image; import 'package:flutter/foundation.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/image_data.dart'; +import '../painting/image_data.dart'; void main() { testWidgets('Verify Image resets its RenderImage when changing providers', (WidgetTester tester) async { diff --git a/packages/flutter/test/widgets/obscured_animated_image.dart b/packages/flutter/test/widgets/obscured_animated_image.dart index 1a449314aa4..41ff442f569 100644 --- a/packages/flutter/test/widgets/obscured_animated_image.dart +++ b/packages/flutter/test/widgets/obscured_animated_image.dart @@ -9,9 +9,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; -import '../services/fake_codec.dart'; -import '../services/fake_image_provider.dart'; -import '../services/image_data.dart'; +import '../painting/fake_codec.dart'; +import '../painting/fake_image_provider.dart'; +import '../painting/image_data.dart'; Future main() async { final FakeCodec fakeCodec = await FakeCodec.fromData(new Uint8List.fromList(kAnimatedGif)); diff --git a/packages/flutter_driver/lib/src/extension/extension.dart b/packages/flutter_driver/lib/src/extension/extension.dart index 05cee0c0122..95ab580abaf 100644 --- a/packages/flutter_driver/lib/src/extension/extension.dart +++ b/packages/flutter_driver/lib/src/extension/extension.dart @@ -35,7 +35,7 @@ const String _extensionMethod = 'ext.flutter.$_extensionMethodName'; /// eventually completes to a string response. typedef Future DataHandler(String message); -class _DriverBinding extends BindingBase with SchedulerBinding, GestureBinding, ServicesBinding, RendererBinding, WidgetsBinding { +class _DriverBinding extends BindingBase with ServicesBinding, SchedulerBinding, GestureBinding, PaintingBinding, RendererBinding, WidgetsBinding { _DriverBinding(this._handler); final DataHandler _handler; diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart index 376a50859c2..f70cf1a3fa9 100644 --- a/packages/flutter_test/lib/src/binding.dart +++ b/packages/flutter_test/lib/src/binding.dart @@ -86,7 +86,8 @@ abstract class TestWidgetsFlutterBinding extends BindingBase with SchedulerBinding, GestureBinding, RendererBinding, - // Services binding omitted to avoid dragging in the licenses code. + ServicesBinding, + PaintingBinding, WidgetsBinding { /// Constructor for [TestWidgetsFlutterBinding]. @@ -150,6 +151,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase super.initInstances(); } + @override + void initLicenses() { + // Do not include any licenses, because we're a test, and the LICENSE file + // doesn't get generated for tests. + } + /// Whether there is currently a test executing. bool get inTest;