#flutter #async-await
Вопрос:
Здесь я пытаюсь получить доступ к камере из приложения, используя пакет камеры, и я новичок в флаттере. Надеюсь, вы поможете мне в этом
Я создал асинхронный метод и объявил в нем переменную, теперь я хочу вызвать объявленный внутри виджета и попытался вызвать его, но там написано «Неопределенное имя»firstCamera»». Я упомянул https://flutter.dev/docs/cookbook/plugins/picture-using-camera. Но я использовал код на другой странице
Заранее спасибо.
это мой код
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)),
);
}
}
Ответ №1:
Согласно документу, вам нужно поместить этот код в main.dart
перед 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),
);
И после этого вы сможете указать firstCamera
виджеты в качестве параметра, и они будут доступны там
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();
}
И вы сможете использовать его в _TakePictureScreenState
таких widget.camera
Кроме того, вы можете создать InheritedWidget
, а затем сможете использовать camera
в более глубоких виджетах
Комментарии:
1. Я пробовал и это, но не знаю, как вызвать переменную на другой странице, потому что мне нужно получить доступ к камере на другой странице.
2. Вам просто нужно передать его через дерево в виджет, где вы должны его использовать
Ответ №2:
Вы должны определить переменную вне метода. Ваш класс _PrivacyPolicyPageState должен выглядеть следующим образом:
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,),
);
}
}
Комментарии:
1. Я попытался это сделать, но там написано «Ошибка: поле» Первая камера «должно быть инициализировано, потому что его тип «Описание камеры» не допускает значения null». И мы не можем использовать поздно
2. Ты в полной безопасности, мой плохой, попробуй
CameraDescription? firstCamera;
и обязательно сначала позвони в камеру()3. Я много искал, но все еще не нашел решения, извините, что снова беспокою вас, но это тоже не работает, в нем говорится: «Ошибка: тип аргумента» Описание камеры? «не может быть присвоен типу параметра «Описание камеры», потому что «Описание камеры?» обнуляется, а «Описание камеры » — нет».
4. Не могли бы вы точно скопировать свой код, пожалуйста?
5. я отредактировал код с изменениями, которые вы мне велели сделать