Check for a null codec in MultiFrameImageStreamCompleter after calling _emitFrame (#165009)
_emitFrame invokes image listeners. A listener callback could remove all of the MultiFrameImageStreamCompleter's listeners, resulting in a _maybeDispose call that destroys the codec. Fixes https://github.com/flutter/flutter/issues/164944 Fixes https://github.com/flutter/flutter/issues/164537
This commit is contained in:
parent
212f66fbe7
commit
6316b48bca
@ -1047,6 +1047,10 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
|
||||
_frameDuration = _nextFrame!.duration;
|
||||
_nextFrame!.image.dispose();
|
||||
_nextFrame = null;
|
||||
if (_codec == null) {
|
||||
// codec was disposed during _emitFrame
|
||||
return;
|
||||
}
|
||||
final int completedCycles = _framesEmitted ~/ _codec!.frameCount;
|
||||
if (_codec!.repetitionCount == -1 || completedCycles <= _codec!.repetitionCount) {
|
||||
_decodeNextFrameAndSchedule();
|
||||
@ -1108,7 +1112,7 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
|
||||
_nextFrame!.image.dispose();
|
||||
_nextFrame = null;
|
||||
|
||||
_codec!.dispose();
|
||||
_codec?.dispose();
|
||||
_codec = null;
|
||||
return;
|
||||
}
|
||||
|
@ -1076,4 +1076,37 @@ void main() {
|
||||
areCreateAndDispose,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('MultiFrameImageStreamCompleter image callback can remove listener', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
final Completer<Codec> completer = Completer<Codec>();
|
||||
final MockCodec mockCodec = MockCodec();
|
||||
mockCodec.frameCount = 1;
|
||||
final ImageStreamCompleter imageStream = MultiFrameImageStreamCompleter(
|
||||
codec: completer.future,
|
||||
scale: 1.0,
|
||||
);
|
||||
|
||||
completer.complete(mockCodec);
|
||||
await tester.idle();
|
||||
expect(mockCodec.numFramesAsked, 0);
|
||||
|
||||
late ImageStreamListener streamListener;
|
||||
|
||||
void listener(ImageInfo image, bool synchronousCall) {
|
||||
addTearDown(image.dispose);
|
||||
imageStream.removeListener(streamListener);
|
||||
}
|
||||
|
||||
streamListener = ImageStreamListener(listener);
|
||||
imageStream.addListener(streamListener);
|
||||
await tester.idle();
|
||||
expect(mockCodec.numFramesAsked, 1);
|
||||
|
||||
final FrameInfo frame = FakeFrameInfo(const Duration(milliseconds: 200), image20x10);
|
||||
mockCodec.completeNextFrame(frame);
|
||||
await tester.idle();
|
||||
expect(mockCodec.disposed, true);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user