I'm new to Flutter and I want to make a simple camera screen using FutureBuilder. This is my code
import 'dart:developer';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'DisplayImagePage.dart';
class CameraScreen extends StatefulWidget {
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
late CameraController _controller;
late final CameraDescription camera;
@override
void initState() {
super.initState();
}
Future<void> prepareCamera() async
{
_getCamera().then((CameraDescription camera)
{
_controller = CameraController(camera, ResolutionPreset.medium);
_controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
);
}
Future<CameraDescription> _getCamera() async
{
final cameras = await availableCameras();
if (cameras.isEmpty) {
// No cameras available
log("Camera is empty!");
}
final firstCamera = cameras.first;
camera = firstCamera;
return firstCamera;
}
Future<String> _takeSelfie(BuildContext context) async {
final XFile image = await _controller.takePicture();
var takenImagePath = image.path;
return takenImagePath;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Take a Selfie'),
),
body: FutureBuilder(
future: prepareCamera(),
builder: (ctx, snapshot)
{
if(snapshot.hasData)
{
log(snapshot.toString());
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: CameraPreview(_controller),
);
}
else if (snapshot.hasError)
{
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
}
return Center(
child: CircularProgressIndicator(),
);
}
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
try {
var path = await _takeSelfie(context);
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DisplayImagePage(imageUrl: path),
));
} catch (e) {
print(e);
}
},
child: Icon(Icons.camera),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
After I give permission to the camera acces, I see this error on the console:
Error: LateInitializationError: Field 'camera' has already been initialized.
_getCamera() is only called once why it tries to assign camera again?
I have tried to wrap _getCamera and PrepareCamera functions together. This did not work.
The
buildmethod is called everytime the state of yourStatefulWidgetis updated, so theFutureBuilderwill callprepareCameraon every build. To prevent this, I suggest you to makecameranullable instead of usinglateinitilization, and make the logic inside_getCameralike this: