Reputation: 467
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
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
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
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
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