samita
samita

Reputation: 175

how to call variable declared in async function into the widget in flutter?

Here I'm trying to access the camera from the app using the camera package and I'm a beginner in a flutter. Hope you'll help me in this

I've created an async method and declared the variable in it now I want to call the declared in inside by widget and tried calling it but it says "Undefined name 'firstCamera'". I've referred to https://flutter.dev/docs/cookbook/plugins/picture-using-camera. But I've used code in another page

Thanks in advance.

this is my code

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

class PrivacyPolicyPage extends StatefulWidget {

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

class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> {


  Future<void> camera() async {

    final cameras = await availableCameras();
    firstCamera = cameras.first;
  }
  CameraDescription? firstCamera;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: TakePictureScreen(camera:firstCamera,),
    );
  }
}

class TakePictureScreen extends StatefulWidget {


  const TakePictureScreen({Key? key,required this.camera}) : super(key: key);
  final CameraDescription camera;

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

class _TakePictureScreenState extends State<TakePictureScreen> {
  late CameraController _controller;
  late Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    // To display the current output from the Camera,
    // create a CameraController.
    _controller = CameraController(
      // Get a specific camera from the list of available cameras.
      widget.camera,
      // Define the resolution to use.
      ResolutionPreset.medium,
    );

    // Next, initialize the controller. This returns a Future.
    _initializeControllerFuture = _controller.initialize();
    @override
    void dispose() {
      // Dispose of the controller when the widget is disposed.
      _controller.dispose();
      super.dispose();
    }

  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context,snapshot){
          if(snapshot.connectionState == ConnectionState.done){
            //If the Future is complete, display the preview.
            return CameraPreview(_controller);

          }
          else{
          //Other wise,display a loading indicator
            return const Center(child:CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          try{
            await _initializeControllerFuture;
            final image = await _controller.takePicture();
            await Navigator.of(context).push(
              MaterialPageRoute(
                builder:(context) => DisplayPictureScreen(
                  imagePath:image.path,
                )
              )
            );
          } catch(e){
            //If an error occurs, log the error to the console.
            print(e);
          }

        },
        child: const Icon(Icons.camera),
      ),
    );
  }
}

class DisplayPictureScreen extends StatelessWidget {
  final String imagePath;
  const DisplayPictureScreen({Key? key, required this.imagePath}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:const Text("Display the Picture")),
      body:Image.file(File(imagePath)),
    );
  }
}

Upvotes: 2

Views: 1027

Answers (2)

Gabriel Costache
Gabriel Costache

Reputation: 969

You have to define the variable outside the method. Your _PrivacyPolicyPageState class should look like this:

class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> {

  // Define outside
  CameraDescription firstCamera;

  Future<void> camera() async {
    // Obtain a list of the available cameras on the device.
    final cameras = await availableCameras();

    // Get a specific camera from the list of available cameras.
    // Assigne a value to firstCamera variable
    firstCamera = cameras.first;

  }
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: TakePictureScreen(camera:firstCamera,),
    );
  }
}

Upvotes: 1

no_fate
no_fate

Reputation: 1705

According the doc, You need to put that code in the main.dart before the runApp():

// Ensure that plugin services are initialized so that 
// `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();

// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();

// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;

runApp(
  PrivacyPolicyPage(camera: camera),
);

And after that you will be able to put firstCamera in widgets as parameter and it will be available there

class PrivacyPolicyPage extends StatelessWidget {
    PrivacyPolicyPage(required this.camera);
    final CameraDescription camera;

    @override
    Widget build(BuildContext context) {
    return SafeArea(
        child: TakePictureScreen(camera:camera),
    );
  }
}

class TakePictureScreen extends StatefulWidget {
    const TakePictureScreen({Key? key,required this.camera}) : 
        super(key: key);
    final CameraDescription camera;

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

And you will be able to use it in _TakePictureScreenState like widget.camera

Also, you can create an InheritedWidget, and then you will be able to use camera in the deeper widgets

Upvotes: 0

Related Questions