You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 23:42:01