Flutter中如何在Widget中调用async函数内声明的变量
存在的问题
- 异步获取相机列表的
camera()方法从未被触发执行,firstCamera始终为初始null值 TakePictureScreen要求传入的camera参数为非空CameraDescription类型,直接传入可空的firstCamera会触发类型报错_TakePictureScreenState中的dispose方法错误嵌套在initState内部,属于语法错误- 没有处理相机加载完成前的占位状态,直接传递null值给相机页会导致崩溃
修复后完整代码
import 'package:flutter/material.dart'; import 'dart:io'; import 'package:camera/camera.dart'; class PrivacyPolicyPage extends StatefulWidget { @override _PrivacyPolicyPageState createState() => _PrivacyPolicyPageState(); } class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> { CameraDescription? firstCamera; bool _isCameraLoading = true; @override void initState() { super.initState(); _initCamera(); } Future<void> _initCamera() async { final cameras = await availableCameras(); setState(() { firstCamera = cameras.first; _isCameraLoading = false; }); } @override Widget build(BuildContext context) { return SafeArea( child: _isCameraLoading ? const Center(child: CircularProgressIndicator()) : 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(); _controller = CameraController( widget.camera, ResolutionPreset.medium, ); _initializeControllerFuture = _controller.initialize(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<void>( future: _initializeControllerFuture, builder: (context,snapshot){ if(snapshot.connectionState == ConnectionState.done){ return CameraPreview(_controller); } else{ return const Center(child:CircularProgressIndicator()); } }, ), floatingActionButton: FloatingActionButton( onPressed: () async { try{ await _initializeControllerFuture; final image = await _controller.takePicture(); if (!mounted) return; await Navigator.of(context).push( MaterialPageRoute( builder:(context) => DisplayPictureScreen( imagePath:image.path, ) ) ); } catch(e){ 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)), ); } }
额外优化说明
- 新增了相机加载中的占位加载态,避免空值异常
- 增加了
mounted判断,防止页面销毁后执行上下文操作触发异常 - 把
dispose方法移出了initState,修复语法错误 - 页面初始化时自动触发相机获取逻辑,保证进入页面即可正常加载相机
内容的提问来源于stack exchange,提问作者samita
相关产品推荐
相关产品推荐

