Fix single frame image is decoded even cached (#82533)
* Fix single frame image is decoded even cached * Add MultiFrameImageStreamCompleter decode test for one frame image
This commit is contained in:
parent
46cdf890b1
commit
1cd677c1b0
@ -974,7 +974,7 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void addListener(ImageStreamListener listener) {
|
void addListener(ImageStreamListener listener) {
|
||||||
if (!hasListeners && _codec != null)
|
if (!hasListeners && _codec != null && (_currentImage == null || _codec!.frameCount > 1))
|
||||||
_decodeNextFrameAndSchedule();
|
_decodeNextFrameAndSchedule();
|
||||||
super.addListener(listener);
|
super.addListener(listener);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ class FakeCodec implements ui.Codec {
|
|||||||
final int _repetitionCount;
|
final int _repetitionCount;
|
||||||
final List<ui.FrameInfo> _frameInfos;
|
final List<ui.FrameInfo> _frameInfos;
|
||||||
int _nextFrame = 0;
|
int _nextFrame = 0;
|
||||||
|
int _numFramesAsked = 0;
|
||||||
|
|
||||||
/// Creates a FakeCodec from encoded image data.
|
/// Creates a FakeCodec from encoded image data.
|
||||||
///
|
///
|
||||||
@ -38,8 +39,11 @@ class FakeCodec implements ui.Codec {
|
|||||||
@override
|
@override
|
||||||
int get repetitionCount => _repetitionCount;
|
int get repetitionCount => _repetitionCount;
|
||||||
|
|
||||||
|
int get numFramesAsked => _numFramesAsked;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ui.FrameInfo> getNextFrame() {
|
Future<ui.FrameInfo> getNextFrame() {
|
||||||
|
_numFramesAsked += 1;
|
||||||
final SynchronousFuture<ui.FrameInfo> result =
|
final SynchronousFuture<ui.FrameInfo> result =
|
||||||
SynchronousFuture<ui.FrameInfo>(_frameInfos[_nextFrame]);
|
SynchronousFuture<ui.FrameInfo>(_frameInfos[_nextFrame]);
|
||||||
_nextFrame = (_nextFrame + 1) % _frameCount;
|
_nextFrame = (_nextFrame + 1) % _frameCount;
|
||||||
|
@ -3,12 +3,16 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
import 'package:flutter/scheduler.dart' show timeDilation, SchedulerBinding;
|
import 'package:flutter/scheduler.dart' show timeDilation, SchedulerBinding;
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../image_data.dart';
|
||||||
|
import 'fake_codec.dart';
|
||||||
|
|
||||||
class FakeFrameInfo implements FrameInfo {
|
class FakeFrameInfo implements FrameInfo {
|
||||||
const FakeFrameInfo(this._duration, this._image);
|
const FakeFrameInfo(this._duration, this._image);
|
||||||
|
|
||||||
@ -780,6 +784,32 @@ void main() {
|
|||||||
handle.dispose();
|
handle.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('MultiFrameImageStreamCompleter - one frame image should only be decoded once', () async {
|
||||||
|
final FakeCodec oneFrameCodec = await FakeCodec.fromData(Uint8List.fromList(kTransparentImage));
|
||||||
|
final Completer<Codec> codecCompleter = Completer<Codec>();
|
||||||
|
final Completer<void> decodeCompleter = Completer<void>();
|
||||||
|
final ImageStreamCompleter imageStream = MultiFrameImageStreamCompleter(
|
||||||
|
codec: codecCompleter.future,
|
||||||
|
scale: 1.0,
|
||||||
|
);
|
||||||
|
final ImageStreamListener imageListener = ImageStreamListener((ImageInfo info, bool syncCall) {
|
||||||
|
decodeCompleter.complete();
|
||||||
|
});
|
||||||
|
|
||||||
|
imageStream.keepAlive(); // do not dispose
|
||||||
|
imageStream.addListener(imageListener);
|
||||||
|
codecCompleter.complete(oneFrameCodec);
|
||||||
|
await decodeCompleter.future;
|
||||||
|
|
||||||
|
imageStream.removeListener(imageListener);
|
||||||
|
expect(oneFrameCodec.numFramesAsked, 1);
|
||||||
|
|
||||||
|
// Adding a new listener for decoded imageSteam, the one frame image should
|
||||||
|
// not be decoded again.
|
||||||
|
imageStream.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {}));
|
||||||
|
expect(oneFrameCodec.numFramesAsked, 1);
|
||||||
|
}); // https://github.com/flutter/flutter/issues/82532
|
||||||
|
|
||||||
// TODO(amirh): enable this once WidgetTester supports flushTimers.
|
// TODO(amirh): enable this once WidgetTester supports flushTimers.
|
||||||
// https://github.com/flutter/flutter/issues/30344
|
// https://github.com/flutter/flutter/issues/30344
|
||||||
// testWidgets('remove and add listener before a delayed frame is scheduled', (WidgetTester tester) async {
|
// testWidgets('remove and add listener before a delayed frame is scheduled', (WidgetTester tester) async {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user