[camerax] Fixes unawaited_futures violations (#4337)

Fixes `unawaited_futures` violations in `camera_android_camerax` plugin. The only `await`s that I did not add are those related to closing/disposing native objects that shouldn't require us to wait for completion.

Part of https://github.com/flutter/flutter/issues/127323.
This commit is contained in:
Camille Simon
2023-07-05 10:28:59 -07:00
committed by GitHub
parent 415bf6dfe9
commit 1809a6c815
10 changed files with 32 additions and 37 deletions

View File

@ -1,3 +1,7 @@
## 0.5.0+8
* Fixes unawaited_futures violations.
## 0.5.0+7 ## 0.5.0+7
* Updates Guava version to 32.0.1. * Updates Guava version to 32.0.1.

View File

@ -1,8 +0,0 @@
# TODO(stuartmorgan): Remove this file and fix all the unawaited_futures
# violations. See https://github.com/flutter/flutter/issues/127323
include: ../../../analysis_options.yaml
linter:
rules:
unawaited_futures: false

View File

@ -526,7 +526,7 @@ class CameraController extends ValueNotifier<CameraValue> {
} }
if (value.isStreamingImages) { if (value.isStreamingImages) {
stopImageStream(); unawaited(stopImageStream());
} }
try { try {

View File

@ -317,9 +317,9 @@ class AndroidCameraCameraX extends CameraPlatform {
@override @override
Future<void> dispose(int cameraId) async { Future<void> dispose(int cameraId) async {
preview?.releaseFlutterSurfaceTexture(); preview?.releaseFlutterSurfaceTexture();
liveCameraState?.removeObservers(); unawaited(liveCameraState?.removeObservers());
processCameraProvider?.unbindAll(); processCameraProvider?.unbindAll();
imageAnalysis?.clearAnalyzer(); unawaited(imageAnalysis?.clearAnalyzer());
} }
/// The camera has been initialized. /// The camera has been initialized.
@ -423,8 +423,8 @@ class AndroidCameraCameraX extends CameraPlatform {
/// [cameraId] not used. /// [cameraId] not used.
@override @override
Future<void> pausePreview(int cameraId) async { Future<void> pausePreview(int cameraId) async {
_unbindUseCaseFromLifecycle(preview!);
_previewIsPaused = true; _previewIsPaused = true;
await _unbindUseCaseFromLifecycle(preview!);
} }
/// Resume the paused preview for the selected camera. /// Resume the paused preview for the selected camera.
@ -432,8 +432,8 @@ class AndroidCameraCameraX extends CameraPlatform {
/// [cameraId] not used. /// [cameraId] not used.
@override @override
Future<void> resumePreview(int cameraId) async { Future<void> resumePreview(int cameraId) async {
await _bindPreviewToLifecycle(cameraId);
_previewIsPaused = false; _previewIsPaused = false;
await _bindPreviewToLifecycle(cameraId);
} }
/// Returns a widget showing a live camera preview. /// Returns a widget showing a live camera preview.
@ -507,7 +507,7 @@ class AndroidCameraCameraX extends CameraPlatform {
if (videoOutputPath == null) { if (videoOutputPath == null) {
// Stop the current active recording as we will be unable to complete it // Stop the current active recording as we will be unable to complete it
// in this error case. // in this error case.
recording!.close(); unawaited(recording!.close());
recording = null; recording = null;
pendingRecording = null; pendingRecording = null;
throw CameraException( throw CameraException(
@ -516,7 +516,7 @@ class AndroidCameraCameraX extends CameraPlatform {
'while reporting success. The platform should always ' 'while reporting success. The platform should always '
'return a valid path or report an error.'); 'return a valid path or report an error.');
} }
recording!.close(); unawaited(recording!.close());
recording = null; recording = null;
pendingRecording = null; pendingRecording = null;
return XFile(videoOutputPath!); return XFile(videoOutputPath!);
@ -526,7 +526,7 @@ class AndroidCameraCameraX extends CameraPlatform {
@override @override
Future<void> pauseVideoRecording(int cameraId) async { Future<void> pauseVideoRecording(int cameraId) async {
if (recording != null) { if (recording != null) {
recording!.pause(); await recording!.pause();
} }
} }
@ -534,7 +534,7 @@ class AndroidCameraCameraX extends CameraPlatform {
@override @override
Future<void> resumeVideoRecording(int cameraId) async { Future<void> resumeVideoRecording(int cameraId) async {
if (recording != null) { if (recording != null) {
recording!.resume(); await recording!.resume();
} }
} }
@ -614,7 +614,7 @@ class AndroidCameraCameraX extends CameraPlatform {
width: imageProxy.width); width: imageProxy.width);
weakThis.target!.cameraImageDataStreamController!.add(cameraImageData); weakThis.target!.cameraImageDataStreamController!.add(cameraImageData);
imageProxy.close(); unawaited(imageProxy.close());
} }
// shouldCreateDetachedObjectForTesting is used to create an Analyzer // shouldCreateDetachedObjectForTesting is used to create an Analyzer
@ -627,7 +627,7 @@ class AndroidCameraCameraX extends CameraPlatform {
// TODO(camsim99): Support resolution configuration. // TODO(camsim99): Support resolution configuration.
// Defaults to YUV_420_888 image format. // Defaults to YUV_420_888 image format.
imageAnalysis = createImageAnalysis(null); imageAnalysis = createImageAnalysis(null);
imageAnalysis!.setAnalyzer(analyzer); unawaited(imageAnalysis!.setAnalyzer(analyzer));
// TODO(camsim99): Reset live camera state observers here when // TODO(camsim99): Reset live camera state observers here when
// https://github.com/flutter/packages/pull/3419 lands. // https://github.com/flutter/packages/pull/3419 lands.
@ -652,7 +652,7 @@ class AndroidCameraCameraX extends CameraPlatform {
/// The [onListen] callback for the stream controller used for image /// The [onListen] callback for the stream controller used for image
/// streaming. /// streaming.
Future<void> _onFrameStreamListen() async { Future<void> _onFrameStreamListen() async {
_configureAndBindImageAnalysisToLifecycle(); await _configureAndBindImageAnalysisToLifecycle();
} }
/// The [onCancel] callback for the stream controller used for image /// The [onCancel] callback for the stream controller used for image
@ -661,7 +661,7 @@ class AndroidCameraCameraX extends CameraPlatform {
/// Removes the previously set analyzer on the [imageAnalysis] instance, since /// Removes the previously set analyzer on the [imageAnalysis] instance, since
/// image information should no longer be streamed. /// image information should no longer be streamed.
FutureOr<void> _onFrameStreamCancel() async { FutureOr<void> _onFrameStreamCancel() async {
imageAnalysis!.clearAnalyzer(); unawaited(imageAnalysis!.clearAnalyzer());
} }
/// Converts between Android ImageFormat constants and [ImageFormatGroup]s. /// Converts between Android ImageFormat constants and [ImageFormatGroup]s.
@ -687,7 +687,7 @@ class AndroidCameraCameraX extends CameraPlatform {
/// removed, as well. /// removed, as well.
Future<void> _updateLiveCameraState(int cameraId) async { Future<void> _updateLiveCameraState(int cameraId) async {
final CameraInfo cameraInfo = await camera!.getCameraInfo(); final CameraInfo cameraInfo = await camera!.getCameraInfo();
liveCameraState?.removeObservers(); await liveCameraState?.removeObservers();
liveCameraState = await cameraInfo.getCameraState(); liveCameraState = await cameraInfo.getCameraState();
await liveCameraState!.observe(_createCameraClosingObserver(cameraId)); await liveCameraState!.observe(_createCameraClosingObserver(cameraId));
} }

View File

@ -139,7 +139,7 @@ class ImageCaptureHostApiImpl extends ImageCaptureHostApi {
assert(identifier != null, assert(identifier != null,
'No ImageCapture has the identifer of that requested to get the resolution information for.'); 'No ImageCapture has the identifer of that requested to get the resolution information for.');
setFlashMode(identifier!, flashMode); await setFlashMode(identifier!, flashMode);
} }
/// Takes a picture with the specified [ImageCapture] instance. /// Takes a picture with the specified [ImageCapture] instance.

View File

@ -67,22 +67,22 @@ class RecordingHostApiImpl extends RecordingHostApi {
/// Closes the specified recording instance. /// Closes the specified recording instance.
Future<void> closeFromInstance(Recording recording) async { Future<void> closeFromInstance(Recording recording) async {
close(instanceManager.getIdentifier(recording)!); await close(instanceManager.getIdentifier(recording)!);
} }
/// Pauses the specified recording instance if active. /// Pauses the specified recording instance if active.
Future<void> pauseFromInstance(Recording recording) async { Future<void> pauseFromInstance(Recording recording) async {
pause(instanceManager.getIdentifier(recording)!); await pause(instanceManager.getIdentifier(recording)!);
} }
/// Resumes the specified recording instance if paused. /// Resumes the specified recording instance if paused.
Future<void> resumeFromInstance(Recording recording) async { Future<void> resumeFromInstance(Recording recording) async {
resume(instanceManager.getIdentifier(recording)!); await resume(instanceManager.getIdentifier(recording)!);
} }
/// Stops the specified recording instance, as if calling closeFromInstance(). /// Stops the specified recording instance, as if calling closeFromInstance().
Future<void> stopFromInstance(Recording recording) async { Future<void> stopFromInstance(Recording recording) async {
stop(instanceManager.getIdentifier(recording)!); await stop(instanceManager.getIdentifier(recording)!);
} }
} }

View File

@ -2,7 +2,7 @@ name: camera_android_camerax
description: Android implementation of the camera plugin using the CameraX library. description: Android implementation of the camera plugin using the CameraX library.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.5.0+7 version: 0.5.0+8
environment: environment:
sdk: ">=2.19.0 <4.0.0" sdk: ">=2.19.0 <4.0.0"

View File

@ -347,7 +347,7 @@ void main() {
camera.liveCameraState = MockLiveCameraState(); camera.liveCameraState = MockLiveCameraState();
camera.imageAnalysis = MockImageAnalysis(); camera.imageAnalysis = MockImageAnalysis();
camera.dispose(3); await camera.dispose(3);
verify(camera.preview!.releaseFlutterSurfaceTexture()); verify(camera.preview!.releaseFlutterSurfaceTexture());
verify(camera.liveCameraState!.removeObservers()); verify(camera.liveCameraState!.removeObservers());
@ -689,7 +689,7 @@ void main() {
final AndroidCameraCameraX camera = AndroidCameraCameraX(); final AndroidCameraCameraX camera = AndroidCameraCameraX();
final MockRecording recording = MockRecording(); final MockRecording recording = MockRecording();
camera.recording = recording; camera.recording = recording;
camera.pauseVideoRecording(0); await camera.pauseVideoRecording(0);
verify(recording.pause()); verify(recording.pause());
verifyNoMoreInteractions(recording); verifyNoMoreInteractions(recording);
}); });
@ -698,7 +698,7 @@ void main() {
final AndroidCameraCameraX camera = AndroidCameraCameraX(); final AndroidCameraCameraX camera = AndroidCameraCameraX();
final MockRecording recording = MockRecording(); final MockRecording recording = MockRecording();
camera.recording = recording; camera.recording = recording;
camera.resumeVideoRecording(0); await camera.resumeVideoRecording(0);
verify(recording.resume()); verify(recording.resume());
verifyNoMoreInteractions(recording); verifyNoMoreInteractions(recording);
}); });
@ -974,7 +974,7 @@ void main() {
// Verify camera and cameraInfo were properly updated. // Verify camera and cameraInfo were properly updated.
expect(camera.camera, equals(mockCamera)); expect(camera.camera, equals(mockCamera));
expect(camera.cameraInfo, equals(mockCameraInfo)); expect(camera.cameraInfo, equals(mockCameraInfo));
onStreamedFrameAvailableSubscription.cancel(); await onStreamedFrameAvailableSubscription.cancel();
}); });
test( test(

View File

@ -37,7 +37,7 @@ void main() {
instanceManager.addHostCreatedInstance(recording, recordingId, instanceManager.addHostCreatedInstance(recording, recordingId,
onCopy: (_) => Recording.detached(instanceManager: instanceManager)); onCopy: (_) => Recording.detached(instanceManager: instanceManager));
recording.close(); await recording.close();
verify(mockApi.close(recordingId)); verify(mockApi.close(recordingId));
}); });
@ -57,7 +57,7 @@ void main() {
instanceManager.addHostCreatedInstance(recording, recordingId, instanceManager.addHostCreatedInstance(recording, recordingId,
onCopy: (_) => Recording.detached(instanceManager: instanceManager)); onCopy: (_) => Recording.detached(instanceManager: instanceManager));
recording.pause(); await recording.pause();
verify(mockApi.pause(recordingId)); verify(mockApi.pause(recordingId));
}); });
@ -77,7 +77,7 @@ void main() {
instanceManager.addHostCreatedInstance(recording, recordingId, instanceManager.addHostCreatedInstance(recording, recordingId,
onCopy: (_) => Recording.detached(instanceManager: instanceManager)); onCopy: (_) => Recording.detached(instanceManager: instanceManager));
recording.resume(); await recording.resume();
verify(mockApi.resume(recordingId)); verify(mockApi.resume(recordingId));
}); });
@ -97,7 +97,7 @@ void main() {
instanceManager.addHostCreatedInstance(recording, recordingId, instanceManager.addHostCreatedInstance(recording, recordingId,
onCopy: (_) => Recording.detached(instanceManager: instanceManager)); onCopy: (_) => Recording.detached(instanceManager: instanceManager));
recording.stop(); await recording.stop();
verify(mockApi.stop(recordingId)); verify(mockApi.stop(recordingId));
}); });

View File

@ -13,7 +13,6 @@
# Temporary opt-outs of unawaited_futures; see # Temporary opt-outs of unawaited_futures; see
# https://github.com/flutter/flutter/issues/127323 # https://github.com/flutter/flutter/issues/127323
- camera/camera_android_camerax
- webview_flutter/webview_flutter - webview_flutter/webview_flutter
- webview_flutter/webview_flutter_android - webview_flutter/webview_flutter_android
- webview_flutter/webview_flutter_wkwebview - webview_flutter/webview_flutter_wkwebview