rameez khan
rameez khan

Reputation: 359

Flutter LateError on controller has not been initialized

When I try to call my widget it's showing an error on the controller that _controller is not initialized I try to set it in initstate.

class CameraApp extends StatefulWidget {
  final dynamic loadingWidget;
  CameraApp(this.loadingWidget);

  _CameraAppState createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> with WidgetsBindingObserver {
  late List<CameraDescription> _cameras;
  late CameraController _controller;
  int _selected = 0;

  @override
  void initState() {
    CameraController _controller;
    super.initState();
    setupCamera();
    WidgetsBinding.instance!.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance!.addObserver(this);
    _controller.dispose();
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    if (_controller == null || !_controller.value.isInitialized) {
      return;
    }

    if (state == AppLifecycleState.inactive) {
      _controller.dispose();
    } else if (state == AppLifecycleState.resumed) {
      setupCamera();
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_controller == null) {
      if (widget.loadingWidget != null) {
        return widget.loadingWidget;
      } else {
        return Container(
          color: Colors.black,
        );
      }
    } else {
      return CameraPreview(_controller);
    }
  }

  Future<void> setupCamera() async {
    await [
      Permission.camera,
    ].request();
    _cameras = await availableCameras();
    var controller = await selectCamera();
    setState(() => _controller = controller);
  }

  selectCamera() async {
    var controller =
        CameraController(_cameras[_selected], ResolutionPreset.max);
    await controller.initialize();
    return controller;
  }

  toggleCamera() async {
    int newSelected = (_selected + 1) % _cameras.length;
    _selected = newSelected;

    var controller = await selectCamera();
    setState(() => _controller = controller);
  }
}

I am showing this camera on some widgets but don't figure out how to solve this issue. Maybe because of late it's causing an issue. Showing every time when its load i also try to add contoller.initialize(); in initstate but not working

enter image description here

Upvotes: 1

Views: 3680

Answers (2)

suraj kumar patel
suraj kumar patel

Reputation: 1

CameraController _controller = null; 

It can't take null value.

Upvotes: 0

h8moss
h8moss

Reputation: 5020

LateError means a variable declared using the late keyword has not been initialized by the time you try to use it, as a general rule, I try to never use the late keyword unless there is no better way to achieve what I want because it tends to cause hard to find errors.

So you have two late variables, _controller and _cameras.

both initialize on the setupCamera method, which is asynchronous and gets called on initState, but the problem I believe is that initState does not wait for them to finish initializing before running build, where you try to read _controller and, because you have yet to assign it, you get a LateError.

If my assertion is correct, it should be a relatively simple fix:

from:

late List<CameraDescription> _cameras;
late CameraController _controller;

to:

List<CameraDescription> _cameras = []; // could also be null I guess.
CameraController _controller = null;

You already have null checks everywhere in case _controller is null, I believe you should take advantage of that so that if build runs before _controller has a value assigned, you get the loading widget.

Upvotes: 1

Related Questions