You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
My app happened to load identical thumbhashes in a list, and I realized that the current version of thumbhash toImage() never got loaded from the cache. They blink every time you scroll up and down. (Already set gaplessPlayback: true)
The == operator and hashCode for Uint8List don't work as expected (see dart-lang/sdk#16335). The code provided below is a minimal example that you can use instead of toImage(). In the Flutter framework, images are cached, but if you use MemoryImage, it won't utilize the cache because it relies on the Uint8List hashCode, which means it will never be the same even if the content is identical.
import'dart:async';
import'package:flutter/foundation.dart';
import'package:flutter/material.dart';
import'package:thumbhash/thumbhash.dart'as thumb;
import'dart:ui'as ui;
Future<ui.Image> thumbHashDecodeImage({
requiredUint8List thumbHash,
}) async {
final completer =Completer<ui.Image>();
final image = thumb.thumbHashToRGBA(thumbHash);
ui.decodeImageFromPixels(image.rgba, image.width, image.height,
ui.PixelFormat.rgba8888, completer.complete);
return completer.future;
}
classThumbHashImageextendsImageProvider<ThumbHashImage> {
/// Creates an object that decodes a [thumbHash] as an image. /// /// The arguments must not be null.constThumbHashImage(this.thumbHash, {this.scale =1.0});
/// The bytes to decode into an image.finalUint8List thumbHash;
/// The scale to place in the [ImageInfo] object of the image.finaldouble scale;
@overrideFuture<ThumbHashImage> obtainKey(ImageConfiguration configuration) =>SynchronousFuture<ThumbHashImage>(this);
@overrideImageStreamCompleterload(ThumbHashImage key, DecoderCallback decode) =>OneFrameImageStreamCompleter(_loadAsync(key));
Future<ImageInfo> _loadAsync(ThumbHashImage key) async {
assert(key ==this);
final image =awaitthumbHashDecodeImage(
thumbHash: thumbHash,
);
returnImageInfo(image: image, scale: key.scale);
}
@overridebooloperator==(Object other) => other.runtimeType != runtimeType
?false: other isThumbHashImage&&memEquals(thumbHash, other.thumbHash) &&
other.scale == scale;
@overrideintget hashCode => thumbHash.reduce((value, element) => value + element.hashCode);
@overrideStringtoString() =>'$runtimeType($thumbHash, scale: $scale)';
}
boolmemEquals(Uint8List bytes1, Uint8List bytes2) {
if (identical(bytes1, bytes2)) {
returntrue;
}
if (bytes1.lengthInBytes != bytes2.lengthInBytes) {
returnfalse;
}
// Treat the original byte lists as lists of 8-byte words.var numWords = bytes1.lengthInBytes ~/8;
var words1 = bytes1.buffer.asUint64List(0, numWords);
var words2 = bytes2.buffer.asUint64List(0, numWords);
for (var i =0; i < words1.length; i +=1) {
if (words1[i] != words2[i]) {
returnfalse;
}
}
// Compare any remaining bytes.for (var i = words1.lengthInBytes; i < bytes1.lengthInBytes; i +=1) {
if (bytes1[i] != bytes2[i]) {
returnfalse;
}
}
returntrue;
}
hashCode can be improved with a better hashCode implementation.
The text was updated successfully, but these errors were encountered:
My app happened to load identical thumbhashes in a list, and I realized that the current version of thumbhash
toImage()
never got loaded from the cache. They blink every time you scroll up and down. (Already set gaplessPlayback: true)The
==
operator andhashCode
for Uint8List don't work as expected (see dart-lang/sdk#16335). The code provided below is a minimal example that you can use instead oftoImage()
. In the Flutter framework, images are cached, but if you useMemoryImage
, it won't utilize the cache because it relies on the Uint8List hashCode, which means it will never be the same even if the content is identical.hashCode can be improved with a better hashCode implementation.
The text was updated successfully, but these errors were encountered: