Nidew
Nidew

Reputation: 467

LateInitializationError: Field 'cameras' has not been initialized

LateInitializationError: Field 'cameras' has not been initialized.

I'm new to flutter and learn creating a chat app and now I want to enable camera. but im getting above error in my code. how can I solve this. appreciate your help on this.

CameraScreen.dart

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


late List <CameraDescription> cameras;


class CameraScreen extends StatefulWidget {
  const CameraScreen({Key? key}) : super(key: key);

  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {

  late CameraController _cameraController;

  late Future<void> cameraValue;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _cameraController = CameraController(cameras[0],ResolutionPreset.high);
    cameraValue = _cameraController.initialize();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
      children: [
        FutureBuilder(
            future: cameraValue,
            builder: (context,snapshot) {
          if(snapshot.connectionState==ConnectionState.done){
            return CameraPreview(_cameraController);
          }
          else{
            return Center(
              child: CircularProgressIndicator(),
            );

          }
        }
        )
      ],
      ),
    );
  }
}

main.dart

Future <void> main() async{
  WidgetsFlutterBinding.ensureInitialized();
  cameras =await availableCameras();
  runApp(const MyApp());
}

Upvotes: 1

Views: 7596

Answers (4)

ggimenez
ggimenez

Reputation: 85

For the record, I had this exact same issue. I fixed it by changing the type of the future to:

Future<void>? cameraValue;

I just removed the late and made it nullable.

Then, in the build function, I'm returning a spinner if cameraValue is null:

  @override
  Widget build(BuildContext context) {
    if (cameraValue  == null) {
      return spinner; // Return whatever you want here
    }

Hope it helps somebody else at least.

Upvotes: 1

tannaom29
tannaom29

Reputation: 11

If you are getting Red Screen with Yellow text over it while running camera, then ...

Run the app again in terminal and it will work

'After running again it will ask for permission, click allow while using the app!'

Upvotes: 1

salihgueler
salihgueler

Reputation: 3622

At the moment of you try to reach out to the cameras, you do not have access to it. You need to wait for the cameras to be loaded and then call the CameraScreen.

I would suggest doing the following:

/// main.dart
Future <void> main() async{
  WidgetsFlutterBinding.ensureInitialized();
  final cameras =await availableCameras();
  runApp(const MyApp(cameras: cameras));
}
/// MyApp.dart

class MyApp extends StatelessWidget {
  const MyApp({required this.cameras, Key? key}) : super(key: key);
  final List<CameraDescription> cameras;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
       home: Scaffold(
          body: CameraScreen(cameras: cameras),
       ),
    );
  }
}
/// CameraScreen.dart
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';

class CameraScreen extends StatefulWidget {
  const CameraScreen({required this.cameras, Key? key}) : super(key: key);
  final List<CameraDescription> cameras;

  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {

  late CameraController _cameraController;

  late Future<void> cameraValue;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _cameraController = CameraController(widget.cameras[0],ResolutionPreset.high);
    cameraValue = _cameraController.initialize();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
      children: [
        FutureBuilder(
            future: cameraValue,
            builder: (context,snapshot) {
          if(snapshot.connectionState==ConnectionState.done){
            return CameraPreview(_cameraController);
          }
          else{
            return Center(
              child: CircularProgressIndicator(),
            );

          }
        }
        )
      ],
      ),
    );
  }
}

Upvotes: 2

Carlos Sandoval
Carlos Sandoval

Reputation: 867

You are not initializing you cameras object in your cameras.dart file, you are doing that on your main file, but those instances are not the same. If you are following the example in https://pub.dev/packages/camera be aware that main and camera widget are on the same file so the instance of cameras is unique.

If you want to have separate files for main and your widget you should pass the camera instance via the constructor. Something like:

Future <void> main() async{
  WidgetsFlutterBinding.ensureInitialized();
  cameras =await availableCameras();
  runApp(const MyApp(cameras: cameras));
}

and your widget should be something like this:

class CameraScreen extends StatefulWidget {
List <CameraDescription> cameras;
  const CameraScreen({Key? key, required this.cameras}) : super(key: key);

  @override
  _CameraScreenState createState() => _CameraScreenState();
}

Upvotes: 2

Related Questions