Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing ReaderWidget before it becomes ready causes error #73

Open
kaboc opened this issue Jan 6, 2023 · 3 comments
Open

Removing ReaderWidget before it becomes ready causes error #73

kaboc opened this issue Jan 6, 2023 · 3 comments

Comments

@kaboc
Copy link

kaboc commented Jan 6, 2023

import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Scaffold(
          body: Center(
            child: ElevatedButton(
              onPressed: () => showDialog(
                context: context,
                builder: (_) => const _Dialog(),
              ),
              child: const Text('Open scan dialog'),
            ),
          ),
        ),
      ),
    );
  }
}

class _Dialog extends StatelessWidget {
  const _Dialog();

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      content: AspectRatio(
        aspectRatio: 3 / 4,
        child: ReaderWidget(onScan: (_) {}),
      ),
      actions: [
        ElevatedButton(
          onPressed: () => Navigator.of(context).pop(),
          child: const Text('Close'),
        ),
      ],
    );
  }
}

Steps to reproduce:

  1. Tap on the "Open scan dialog" button.
  2. It opens a dialog with ReaderWidget.
  3. Close the dialog before the camera preview appears.
  4. See the output in the console.

It gives different errors depending on how quickly the dialog is closed.

a) If it is very quick:

I/flutter (16061): Error: A CameraController was used after being disposed.
I/flutter (16061): Once you have called dispose() on a CameraController, it can no longer be used.
E/flutter (16061): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: A CameraController was used after being disposed.
E/flutter (16061): Once you have called dispose() on a CameraController, it can no longer be used.
E/flutter (16061): #0      ChangeNotifier.debugAssertNotDisposed.<anonymous closure> (package:flutter/src/foundation/change_notifier.dart:147:9)
E/flutter (16061): #1      ChangeNotifier.debugAssertNotDisposed (package:flutter/src/foundation/change_notifier.dart:154:6)
E/flutter (16061): #2      ChangeNotifier.addListener (package:flutter/src/foundation/change_notifier.dart:207:27)
E/flutter (16061): #3      _ReaderWidgetState.onNewCameraSelected (package:flutter_zxing/src/ui/reader_widget.dart:158:17)

b) If it is a little later:

======== Exception caught by services library ======================================================
The following PlatformException was thrown while activating platform stream on channel plugins.flutter.io/camera_android/imageStream:
PlatformException(error, Attempt to invoke virtual method 'void android.media.ImageReader.setOnImageAvailableListener(android.media.ImageReader$OnImageAvailableListener, android.os.Handler)' on a null object reference, null, null)

When the exception was thrown, this was the stack: 
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
#1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:296:18)
<asynchronous suspension>
#2      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:637:9)
<asynchronous suspension>
====================================================================================================
@kaboc
Copy link
Author

kaboc commented Jan 6, 2023

Regarding the first case, I think the non-null assertion operator (!) should be avoided when methods are called on the CameraController. Even if it is checked before the try block that the controller is not null, it is possible that it turns to null while futures are awaited. It is safer to use ? instead.

if (controller == null) {
return;
}
try {
await controller!.initialize();
await controller!.setFlashMode(FlashMode.off);
_maxZoomLevel = await controller!.getMaxZoomLevel();
_minZoomLevel = await controller!.getMinZoomLevel();
controller!.startImageStream(processImageStream);
} on CameraException catch (e) {
debugPrint('${e.code}: ${e.description}');
} catch (e) {
debugPrint('Error: $e');
}
controller!.addListener(rebuildOnMount);
rebuildOnMount();
widget.onControllerCreated?.call(controller);

@khoren93
Copy link
Owner

khoren93 commented Jan 6, 2023

Hi there!

It looks like this issue has been fixed in the main branch.
Please check to see if the issue has been resolved for you and let me know if you have any further issues or questions.

Thanks for bringing this to my attention!

@kaboc
Copy link
Author

kaboc commented Jan 7, 2023

@khoren93
Hi, thanks for quickly looking into the issue.

I ran the same code with the latest commit in the main branch.

a) The issue still seems to be around, although the output is different now. It has the first two lines without stack trace.

I/flutter (22532): Error: A CameraController was used after being disposed.
I/flutter (22532): Once you have called dispose() on a CameraController, it can no longer be used.

b) The app raises the same error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants