mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Hoist knowledge of image_cache into widgets/basic.dart
Previously, RenderImage knew about image_cache and expected to work in terms of URLs. Now RenderImage works directly with sky.Image and it's the job of the widgets system to interact with the network cache. At the widgets layer, I've factored this work into three parts: 1) A wrapper for RenderImage that works in terms of sky.Image. 2) A component that can deal with any sort of Future<sky.Image>. 3) A NetworkImage component that translates relative URLs into Future<sky.Image> using the image_cache. A future CL will add a peer to NetworkImage that gets Future<sky.Image>s from an asset bundle. R=ianh@google.com, jackson@google.com Review URL: https://codereview.chromium.org/1218023013.
This commit is contained in:
parent
08fce0e905
commit
70b8347fe1
@ -14,7 +14,7 @@ class ContainerApp extends App {
|
||||
padding: new EdgeDims.all(10.0),
|
||||
margin: new EdgeDims.all(10.0),
|
||||
decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)),
|
||||
child: new Image(
|
||||
child: new NetworkImage(
|
||||
src: "https://www.dartlang.org/logos/dart-logo.png",
|
||||
size: new Size(300.0, 300.0)
|
||||
)
|
||||
|
||||
@ -3,52 +3,26 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:sky' as sky;
|
||||
import 'dart:collection';
|
||||
import 'dart:sky' as sky;
|
||||
|
||||
import 'package:mojom/mojo/url_response.mojom.dart';
|
||||
|
||||
import 'fetch.dart';
|
||||
|
||||
final HashMap<String, List<sky.ImageDecoderCallback>> _pendingRequests =
|
||||
new HashMap<String, List<sky.ImageDecoderCallback>>();
|
||||
|
||||
final HashMap<String, sky.Image> _completedRequests =
|
||||
new HashMap<String, sky.Image>();
|
||||
|
||||
void _loadComplete(String url, sky.Image image) {
|
||||
_completedRequests[url] = image;
|
||||
_pendingRequests[url].forEach((c) => c(image));
|
||||
_pendingRequests.remove(url);
|
||||
}
|
||||
|
||||
void _load(String url, sky.ImageDecoderCallback callback) {
|
||||
sky.Image result = _completedRequests[url];
|
||||
if (result != null) {
|
||||
callback(_completedRequests[url]);
|
||||
return;
|
||||
}
|
||||
|
||||
bool newRequest = false;
|
||||
_pendingRequests.putIfAbsent(url, () {
|
||||
newRequest = true;
|
||||
return new List<sky.ImageDecoderCallback>();
|
||||
}).add(callback);
|
||||
if (newRequest) {
|
||||
fetchUrl(url).then((UrlResponse response) {
|
||||
if (response.statusCode >= 400) {
|
||||
_loadComplete(url, null);
|
||||
return;
|
||||
}
|
||||
new sky.ImageDecoder(response.body.handle.h, (image) {
|
||||
_loadComplete(url, image);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
final HashMap<String, Future<sky.Image>> _cache =
|
||||
new HashMap<String, Future<sky.Image>>();
|
||||
|
||||
Future<sky.Image> load(String url) {
|
||||
Completer<sky.Image> completer = new Completer<sky.Image>();
|
||||
_load(url, completer.complete);
|
||||
return completer.future;
|
||||
return _cache.putIfAbsent(url, () {
|
||||
Completer<sky.Image> completer = new Completer<sky.Image>();
|
||||
fetchUrl(url).then((UrlResponse response) {
|
||||
if (response.statusCode >= 400) {
|
||||
completer.complete(null);
|
||||
} else {
|
||||
new sky.ImageDecoder(response.body.handle.h, completer.complete);
|
||||
}
|
||||
});
|
||||
return completer.future;
|
||||
});
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import 'dart:sky' as sky;
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
import '../base/debug.dart';
|
||||
import '../mojo/net/image_cache.dart' as image_cache;
|
||||
import '../painting/box_painter.dart';
|
||||
import 'object.dart';
|
||||
|
||||
@ -1015,24 +1014,18 @@ class RenderBaseline extends RenderShiftedBox {
|
||||
|
||||
class RenderImage extends RenderBox {
|
||||
|
||||
RenderImage(String url, Size dimensions) {
|
||||
requestedSize = dimensions;
|
||||
src = url;
|
||||
}
|
||||
RenderImage(sky.Image image, Size requestedSize)
|
||||
: _image = image, _requestedSize = requestedSize;
|
||||
|
||||
sky.Image _image;
|
||||
String _src;
|
||||
String get src => _src;
|
||||
void set src (String value) {
|
||||
if (value == _src)
|
||||
sky.Image get image => _image;
|
||||
void set image (sky.Image value) {
|
||||
if (value == _image)
|
||||
return;
|
||||
_src = value;
|
||||
image_cache.load(_src).then((result) {
|
||||
_image = result;
|
||||
if (requestedSize.width == null || requestedSize.height == null)
|
||||
markNeedsLayout();
|
||||
markNeedsPaint();
|
||||
});
|
||||
_image = value;
|
||||
markNeedsPaint();
|
||||
if (_requestedSize.width == null || _requestedSize.height == null)
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
Size _requestedSize;
|
||||
@ -1114,7 +1107,7 @@ class RenderImage extends RenderBox {
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}url: ${src}\n${prefix}dimensions: ${requestedSize}\n';
|
||||
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}dimensions: ${requestedSize}\n';
|
||||
}
|
||||
|
||||
class RenderDecoratedBox extends RenderProxyBox {
|
||||
|
||||
@ -2,10 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:sky' as sky;
|
||||
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
import '../mojo/net/image_cache.dart' as image_cache;
|
||||
import '../painting/text_style.dart';
|
||||
import '../rendering/block.dart';
|
||||
import '../rendering/box.dart';
|
||||
@ -477,7 +479,7 @@ class Text extends Component {
|
||||
else
|
||||
combinedStyle = defaultStyle;
|
||||
} else {
|
||||
combinedStyle = style;
|
||||
combinedStyle = style;
|
||||
}
|
||||
if (combinedStyle != null)
|
||||
text = new InlineStyle(combinedStyle, [text]);
|
||||
@ -486,27 +488,66 @@ class Text extends Component {
|
||||
}
|
||||
|
||||
class Image extends LeafRenderObjectWrapper {
|
||||
|
||||
Image({
|
||||
src,
|
||||
this.size
|
||||
}) : src = src,
|
||||
super(key: src) {
|
||||
assert(src != null);
|
||||
}
|
||||
Image({ sky.Image image, this.size })
|
||||
: image = image, super(key: image.hashCode.toString());
|
||||
|
||||
RenderImage get root => super.root;
|
||||
RenderImage createNode() => new RenderImage(this.src, this.size);
|
||||
RenderImage createNode() => new RenderImage(image, size);
|
||||
|
||||
final String src;
|
||||
final sky.Image image;
|
||||
final Size size;
|
||||
|
||||
void syncRenderObject(Widget old) {
|
||||
super.syncRenderObject(old);
|
||||
root.src = src;
|
||||
root.image = image;
|
||||
root.requestedSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
class FutureImage extends Component {
|
||||
FutureImage({ this.image, this.size }) : super(stateful: true);
|
||||
|
||||
Future<sky.Image> image;
|
||||
Size size;
|
||||
sky.Image _resolvedImage;
|
||||
|
||||
void didMount() {
|
||||
super.didMount();
|
||||
_resolveImage();
|
||||
}
|
||||
|
||||
void _resolveImage() {
|
||||
image.then((sky.Image resolvedImage) {
|
||||
if (!mounted)
|
||||
return;
|
||||
setState(() {
|
||||
_resolvedImage = resolvedImage;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void syncFields(FutureImage source) {
|
||||
bool needToResolveImage = (image != source.image);
|
||||
image = source.image;
|
||||
size = source.size;
|
||||
if (needToResolveImage)
|
||||
_resolveImage();
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return new Image(image: _resolvedImage, size: size);
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkImage extends Component {
|
||||
NetworkImage({ String src, this.size }) : src = src, super(key: src);
|
||||
|
||||
final String src;
|
||||
final Size size;
|
||||
|
||||
Widget build() {
|
||||
return new FutureImage(image: image_cache.load(src), size: size);
|
||||
}
|
||||
}
|
||||
|
||||
class WidgetToRenderBoxAdapter extends LeafRenderObjectWrapper {
|
||||
|
||||
@ -29,7 +29,7 @@ class Icon extends Component {
|
||||
// TODO(eseidel): This clearly isn't correct. Not sure what would be.
|
||||
// Should we use the ios images on ios?
|
||||
String density = 'drawable-xxhdpi';
|
||||
return new Image(
|
||||
return new NetworkImage(
|
||||
size: new Size(size.toDouble(), size.toDouble()),
|
||||
src: '${kAssetBase}/${category}/${density}/ic_${subtype}_${size}dp.png'
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user