Julian Steenbakker

fix: make async initialization and dispose calls in separate async function

@@ -339,6 +339,7 @@ class MethodChannelMobileScanner extends MobileScannerPlatform { @@ -339,6 +339,7 @@ class MethodChannelMobileScanner extends MobileScannerPlatform {
339 339
340 @override 340 @override
341 Future<void> dispose() async { 341 Future<void> dispose() async {
  342 + await updateScanWindow(null);
342 await stop(); 343 await stop();
343 } 344 }
344 } 345 }
@@ -135,7 +135,7 @@ class MobileScanner extends StatefulWidget { @@ -135,7 +135,7 @@ class MobileScanner extends StatefulWidget {
135 135
136 class _MobileScannerState extends State<MobileScanner> 136 class _MobileScannerState extends State<MobileScanner>
137 with WidgetsBindingObserver { 137 with WidgetsBindingObserver {
138 - late final controller = widget.controller ?? MobileScannerController(); 138 + late final MobileScannerController controller;
139 139
140 /// The current scan window. 140 /// The current scan window.
141 Rect? scanWindow; 141 Rect? scanWindow;
@@ -200,7 +200,6 @@ class _MobileScannerState extends State<MobileScanner> @@ -200,7 +200,6 @@ class _MobileScannerState extends State<MobileScanner>
200 return ValueListenableBuilder<MobileScannerState>( 200 return ValueListenableBuilder<MobileScannerState>(
201 valueListenable: controller, 201 valueListenable: controller,
202 builder: (BuildContext context, MobileScannerState value, Widget? child) { 202 builder: (BuildContext context, MobileScannerState value, Widget? child) {
203 -  
204 // If the controller is still initializing, show a black screen, or user provided placeholder 203 // If the controller is still initializing, show a black screen, or user provided placeholder
205 if (!value.isInitialized) { 204 if (!value.isInitialized) {
206 const Widget defaultPlaceholder = ColoredBox(color: Colors.black); 205 const Widget defaultPlaceholder = ColoredBox(color: Colors.black);
@@ -259,8 +258,21 @@ class _MobileScannerState extends State<MobileScanner> @@ -259,8 +258,21 @@ class _MobileScannerState extends State<MobileScanner>
259 258
260 StreamSubscription? _subscription; 259 StreamSubscription? _subscription;
261 260
262 - @override  
263 - void initState() { 261 + Future<void> initController() async {
  262 + // TODO: This will be fixed in another PR
  263 + // If debug mode is enabled, stop the controller first before starting it.
  264 + // If a hot-restart is initiated, the controller won't be stopped, and because
  265 + // there is no way of knowing if a hot-restart has happened, we must assume
  266 + // every start is a hot-restart.
  267 + // if (kDebugMode) {
  268 + // try {
  269 + // await controller.stop();
  270 + // } catch (e) {
  271 + // // Don't do anything if the controller is already stopped.
  272 + // debugPrint('$e');
  273 + // }
  274 + // }
  275 +
264 if (widget.onDetect != null) { 276 if (widget.onDetect != null) {
265 WidgetsBinding.instance.addObserver(this); 277 WidgetsBinding.instance.addObserver(this);
266 _subscription = controller.barcodes.listen( 278 _subscription = controller.barcodes.listen(
@@ -270,31 +282,39 @@ class _MobileScannerState extends State<MobileScanner> @@ -270,31 +282,39 @@ class _MobileScannerState extends State<MobileScanner>
270 ); 282 );
271 } 283 }
272 if (controller.autoStart) { 284 if (controller.autoStart) {
273 - controller.start(); 285 + await controller.start();
  286 + }
  287 + }
  288 +
  289 + Future<void> disposeCamera() async {
  290 + if (controller.autoStart) {
  291 + await controller.stop();
  292 + }
  293 +
  294 + // Dispose default controller if not provided by user
  295 + if (widget.controller == null) {
  296 + await controller.dispose();
  297 + WidgetsBinding.instance.removeObserver(this);
274 } 298 }
  299 + }
  300 +
  301 + @override
  302 + void initState() {
275 super.initState(); 303 super.initState();
  304 + controller = widget.controller ?? MobileScannerController();
  305 + initController();
276 } 306 }
277 307
278 @override 308 @override
279 void dispose() { 309 void dispose() {
280 - super.dispose();  
281 -  
282 if (_subscription != null) { 310 if (_subscription != null) {
283 _subscription!.cancel(); 311 _subscription!.cancel();
284 _subscription = null; 312 _subscription = null;
285 } 313 }
286 314
287 - if (controller.autoStart) {  
288 - controller.stop();  
289 - }  
290 - // When this widget is unmounted, reset the scan window.  
291 - unawaited(controller.updateScanWindow(null)); 315 + disposeCamera();
292 316
293 - // Dispose default controller if not provided by user  
294 - if (widget.controller == null) {  
295 - controller.dispose();  
296 - WidgetsBinding.instance.removeObserver(this);  
297 - } 317 + super.dispose();
298 } 318 }
299 319
300 @override 320 @override