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

Flutter使用camera包调用Android相机抛出NoSuchMethodError异常求助

问题根因

你抛出的NoSuchMethodError: The method '[]' was called on null错误,来源于代码访问cameras[0]时,cameras全局变量还未完成初始化,仍为null值。

具体触发场景说明
  • 你将cameras = await availableCameras();移到initState中时,initState本身不支持异步等待,代码执行到controller = CameraController(cameras[0],...)时,availableCameras的异步操作还未完成,cameras还没有被赋值,直接触发空值调用错误。
  • 你最初版本可正常运行,是因为最初的main函数中补全了WidgetsFlutterBinding.ensureInitialized()的调用,Flutter框架初始化完成后才执行availableCameras获取相机列表,保证cameras在使用前已经完成赋值。
修复方案

第一步:补全平台权限配置

Android端

在android/app/src/main/AndroidManifest.xml的manifest标签下添加相机权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

iOS端

在ios/Runner/Info.plist的dict标签下添加相机权限说明:

<key>NSCameraUsageDescription</key>
<string>需要使用相机完成考勤打卡</string>

第二步:修复代码逻辑

这里提供两种稳定实现方案:

方案1:保留全局相机列表初始化逻辑

在main函数中补全Flutter绑定初始化的调用,保证相机列表获取操作在框架初始化完成后执行:

Future<void> main() async {
  // 新增代码,必须放在所有异步操作之前
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  runApp(MyApp());
}

同时在CameraAppState的build方法中补全空判断,避免极端场景下的空指针:

@override
Widget build(BuildContext context) {
  // 新增controller非空判断
  if (controller == null || !controller.value.isInitialized) {
    return const Center(child: CircularProgressIndicator());
  }
  return RotationTransition(
    turns: AlwaysStoppedAnimation(270 / 360),
    child: CameraPreview(controller),
  );
}

方案2:将相机初始化逻辑全部移入State中(更稳定,避免全局变量风险)

先删除全局的List<CameraDescription> cameras;定义,修改CameraAppState的代码:

class CameraAppState extends State<CameraApp> {
  CameraController? controller; // 改为可空类型

  @override
  void initState() {
    super.initState();
    _initCamera();
  }

  // 独立的异步初始化方法
  Future<void> _initCamera() async {
    // 若使用permission_handler包,可在此处先申请相机权限
    final cameras = await availableCameras();
    if (cameras.isEmpty) return;
    controller = CameraController(cameras[0], ResolutionPreset.medium);
    await controller?.initialize();
    if (mounted) setState(() {});
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (controller == null || !controller!.value.isInitialized) {
      return const Center(child: CircularProgressIndicator());
    }
    return RotationTransition(
      turns: const AlwaysStoppedAnimation(270 / 360),
      child: CameraPreview(controller!),
    );
  }
}
验证说明

修复完成后完全关闭应用进程重新运行,不要使用热重载,避免旧的状态残留导致异常。

内容的提问来源于stack exchange,提问作者Tri yulianto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:09:03