remove autoresume field; make controller required; fix memory leak; fix bug with _restartScanner()
Showing
1 changed file
with
34 additions
and
44 deletions
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 1 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; |
| 2 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
| 3 | import 'package:mobile_scanner/src/mobile_scanner_controller.dart'; | 5 | import 'package:mobile_scanner/src/mobile_scanner_controller.dart'; |
| @@ -11,8 +13,8 @@ typedef MobileScannerArgumentsCallback = void Function( | @@ -11,8 +13,8 @@ typedef MobileScannerArgumentsCallback = void Function( | ||
| 11 | 13 | ||
| 12 | /// A widget showing a live camera preview. | 14 | /// A widget showing a live camera preview. |
| 13 | class MobileScanner extends StatefulWidget { | 15 | class MobileScanner extends StatefulWidget { |
| 14 | - /// The controller of the camera. | ||
| 15 | - final MobileScannerController? controller; | 16 | + /// The controller that manages the barcode scanner. |
| 17 | + final MobileScannerController controller; | ||
| 16 | 18 | ||
| 17 | /// Function that gets called when a Barcode is detected. | 19 | /// Function that gets called when a Barcode is detected. |
| 18 | /// | 20 | /// |
| @@ -35,11 +37,7 @@ class MobileScanner extends StatefulWidget { | @@ -35,11 +37,7 @@ class MobileScanner extends StatefulWidget { | ||
| 35 | /// Create a [MobileScanner] with a [controller]. | 37 | /// Create a [MobileScanner] with a [controller]. |
| 36 | /// The [controller] must have been initialized, using [MobileScannerController.start]. | 38 | /// The [controller] must have been initialized, using [MobileScannerController.start]. |
| 37 | const MobileScanner({ | 39 | const MobileScanner({ |
| 38 | - super.key, | ||
| 39 | - required this.onDetect, | ||
| 40 | - this.onStart, | ||
| 41 | - this.controller, | ||
| 42 | - this.autoResume = true, | 40 | + required this.controller, |
| 43 | this.fit = BoxFit.cover, | 41 | this.fit = BoxFit.cover, |
| 44 | }); | 42 | }); |
| 45 | 43 | ||
| @@ -49,44 +47,53 @@ class MobileScanner extends StatefulWidget { | @@ -49,44 +47,53 @@ class MobileScanner extends StatefulWidget { | ||
| 49 | 47 | ||
| 50 | class _MobileScannerState extends State<MobileScanner> | 48 | class _MobileScannerState extends State<MobileScanner> |
| 51 | with WidgetsBindingObserver { | 49 | with WidgetsBindingObserver { |
| 52 | - late MobileScannerController controller; | 50 | + /// The subscription that listens to barcode detection. |
| 51 | + StreamSubscription<BarcodeCapture>? _barcodesSubscription; | ||
| 52 | + | ||
| 53 | + /// Whether the controller should resume | ||
| 54 | + /// when the application comes back to the foreground. | ||
| 55 | + bool _resumeFromBackground = false; | ||
| 56 | + | ||
| 57 | + /// Restart a previously paused scanner. | ||
| 58 | + void _restartScanner() { | ||
| 59 | + widget.controller.start().then((arguments) { | ||
| 60 | + widget.onScannerRestarted?.call(arguments); | ||
| 61 | + }).catchError((error) { | ||
| 62 | + // The scanner somehow failed to restart. | ||
| 63 | + // There is no way to recover from this, so do nothing. | ||
| 64 | + }); | ||
| 65 | + } | ||
| 53 | 66 | ||
| 54 | @override | 67 | @override |
| 55 | void initState() { | 68 | void initState() { |
| 56 | super.initState(); | 69 | super.initState(); |
| 57 | WidgetsBinding.instance.addObserver(this); | 70 | WidgetsBinding.instance.addObserver(this); |
| 58 | - controller = widget.controller ?? MobileScannerController(); | ||
| 59 | - if (!controller.isStarting) { | ||
| 60 | - _startScanner(); | ||
| 61 | - } | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | - Future<void> _startScanner() async { | ||
| 65 | - final arguments = await controller.start(); | ||
| 66 | - widget.onStart?.call(arguments); | 71 | + _barcodesSubscription = widget.controller.barcodes.listen( |
| 72 | + widget.onBarcodeDetected, | ||
| 73 | + ); | ||
| 67 | } | 74 | } |
| 68 | 75 | ||
| 69 | - bool resumeFromBackground = false; | ||
| 70 | - | ||
| 71 | @override | 76 | @override |
| 72 | void didChangeAppLifecycleState(AppLifecycleState state) { | 77 | void didChangeAppLifecycleState(AppLifecycleState state) { |
| 73 | - // App state changed before it is initialized. | ||
| 74 | - if (controller.isStarting) { | 78 | + // App state changed before the controller was initialized. |
| 79 | + if (widget.controller.isStarting) { | ||
| 75 | return; | 80 | return; |
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | switch (state) { | 83 | switch (state) { |
| 79 | case AppLifecycleState.resumed: | 84 | case AppLifecycleState.resumed: |
| 80 | - resumeFromBackground = false; | ||
| 81 | - _startScanner(); | 85 | + _resumeFromBackground = false; |
| 86 | + _restartScanner(); | ||
| 82 | break; | 87 | break; |
| 83 | case AppLifecycleState.paused: | 88 | case AppLifecycleState.paused: |
| 84 | - resumeFromBackground = true; | 89 | + _resumeFromBackground = true; |
| 85 | break; | 90 | break; |
| 86 | case AppLifecycleState.inactive: | 91 | case AppLifecycleState.inactive: |
| 87 | - if (!resumeFromBackground) controller.stop(); | 92 | + if (!_resumeFromBackground) { |
| 93 | + widget.controller.stop(); | ||
| 94 | + } | ||
| 88 | break; | 95 | break; |
| 89 | - default: | 96 | + case AppLifecycleState.detached: |
| 90 | break; | 97 | break; |
| 91 | } | 98 | } |
| 92 | } | 99 | } |
| @@ -125,26 +132,9 @@ class _MobileScannerState extends State<MobileScanner> | @@ -125,26 +132,9 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 125 | } | 132 | } |
| 126 | 133 | ||
| 127 | @override | 134 | @override |
| 128 | - void didUpdateWidget(covariant MobileScanner oldWidget) { | ||
| 129 | - super.didUpdateWidget(oldWidget); | ||
| 130 | - if (oldWidget.controller == null) { | ||
| 131 | - if (widget.controller != null) { | ||
| 132 | - controller.dispose(); | ||
| 133 | - controller = widget.controller!; | ||
| 134 | - } | ||
| 135 | - } else { | ||
| 136 | - if (widget.controller == null) { | ||
| 137 | - controller = MobileScannerController(); | ||
| 138 | - } else if (oldWidget.controller != widget.controller) { | ||
| 139 | - controller = widget.controller!; | ||
| 140 | - } | ||
| 141 | - } | ||
| 142 | - } | ||
| 143 | - | ||
| 144 | - @override | ||
| 145 | void dispose() { | 135 | void dispose() { |
| 146 | - controller.dispose(); | ||
| 147 | WidgetsBinding.instance.removeObserver(this); | 136 | WidgetsBinding.instance.removeObserver(this); |
| 137 | + _barcodesSubscription?.cancel(); | ||
| 148 | super.dispose(); | 138 | super.dispose(); |
| 149 | } | 139 | } |
| 150 | } | 140 | } |
-
Please register or login to post a comment