提问人:JohannesBug 提问时间:7/13/2023 更新时间:7/13/2023 访问量:37
如何等待异步函数正确完成(flutter、dart)
How do I wait for an asynchronous function to finish correctly (flutter, dart)
问:
我想为一个显示相机预览的 flutter 应用程序构建一个屏幕。为此,我必须异步初始化相机。这会导致异常,因为我在初始化相机之前访问了它。我通过使用 try-catch 块来解决这个问题。但我觉得这是一个肮脏的解决方案。有没有更好的?我正在 android 的 Windows 上开发。这是我为该屏幕编写的完整代码。我用行注释标记了兴趣点。
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
class CameraPreviewPage extends StatefulWidget {
const CameraPreviewPage({super.key});
@override
State<CameraPreviewPage> createState() => _CameraPreviewPageState();
}
class _CameraPreviewPageState extends State<CameraPreviewPage> {
late List<CameraDescription> _cameraDescriptions;
late CameraController _cameraController; //Here I declare the camera object which throws an "late not inizialized" exception
//this function inizializes the object but asynchronously
void initCamera() async {
_cameraDescriptions = await availableCameras();
_cameraController = CameraController(
_cameraDescriptions[0],
ResolutionPreset.high,
enableAudio: false,
);
await _cameraController.initialize().then((value) {
if (!mounted) {
return;
}
setState(() {});
}).catchError((e) {
debugPrint(e);
});
}
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
@override
void initState() {
initCamera();
super.initState();
}
//in this build function the Exception occurs.
// Wrapping the "CameraPreview(_cameraController)," line in a try catch gives me working but ugly(?) code
@override
Widget build(BuildContext context) {
try {
return Scaffold(
body: Stack(
children: [
CameraPreview(_cameraController),
],
),
);
} catch (e) {
return const SizedBox();
}
}
}
我对异步编程和 flutter/dart 本身很陌生。如果这个问题在其他地方得到解答,请把我带到那里,因为我在 google/youtube 上找不到它。
我尝试了 FutureBuilder Widget,但它无法正常工作,也许我不理解它,可悲的是我丢失了代码。
答:
1赞
Niko
7/13/2023
#1
问题是它本身不是一个异步方法,不能等待你的.因此,当方法已被调用时,您正在执行。initState
initCamera
initCamera
build
然后 your 尚未初始化,而是在 build 方法中使用。_cameraController
要解决此问题,您可以根据状态有条件地显示不同的小部件,或者改用小部件。FutureBuilder
使用布尔值时的状态类:
class _CameraPreviewPageState extends State<CameraPreviewPage> {
late List<CameraDescription> _cameraDescriptions;
late CameraController _cameraController; //Here I declare the camera object which throws an "late not inizialized" exception
bool _initialized = false;
//this function inizializes the object but asynchronously
void initCamera() async {
_cameraDescriptions = await availableCameras();
_cameraController = CameraController(
_cameraDescriptions[0],
ResolutionPreset.high,
enableAudio: false,
);
await _cameraController.initialize().then((value) {
if (!mounted) {
return;
}
setState(() {
_initialized = true;
});
}).catchError((e) {
debugPrint(e);
});
}
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
@override
void initState() {
initCamera();
super.initState();
}
//in this build function the Exception occurs.
// Wrapping the "CameraPreview(_cameraController)," line in a try catch gives me working but ugly(?) code
@override
Widget build(BuildContext context) {
try {
return Scaffold(
body: Stack(
children: [
if(_initialized) CameraPreview(_cameraController),
if(!_initialized) Text("loading..."),
],
),
);
} catch (e) {
return const SizedBox();
}
}
}
评论