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
build
method is called everytime the state of yourStatefulWidget
is updated, so theFutureBuilder
will callprepareCamera
on every build. To prevent this, I suggest you to makecamera
nullable instead of usinglate
initilization, and make the logic inside_getCamera
like this: