Flutter :已处置的 CameraController,在已处置的 CameraController 上调用了 buildPreview()

Nib*_*ain 9 video camera android dart flutter

如何正确初始化和处理相机控制器。我在用 camera: ^0.9.4+5

\n

与许多人一起

\n
\n

其他错误

\n
\n

我在单击切换相机按钮时收到此错误:

\n
======== Exception caught by widgets library =======================================================\nThe following CameraException was thrown building ValueListenableBuilder<CameraValue>(dirty, state: _ValueListenableBuilderState<CameraValue>#47f17):\nCameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.)\n
Run Code Online (Sandbox Code Playgroud)\n

这是完整的代码:

\n
class VideoRecorderScreen extends StatefulWidget {\n  @override\n  _VideoRecorderScreenState createState() {\n    return _VideoRecorderScreenState();\n  }\n\n  //final ApplicantData applicantData;\n  final String videorec;\n \n\n  VideoRecorderScreen(this.applicationId, this.name, this.description,\n      this.descriptionHindi, this.videorec,\n      {this.isOpenSubsDashboard = false});\n}\n\nclass _VideoRecorderScreenState extends State<VideoRecorderScreen> {\n  CameraController controller;\n  XFile videoPath;\n  List<CameraDescription> cameras;\n  int selectedCameraIdx = 1;\n  int videoElapseTime = 25;\n  int videoMinElapseTime = 20;\n  \n  bool visibilityStop = false;\n  bool visibilityButtons = false;\n  String timer = "00:00";\n  CountdownTimer cd;\n  bool startRecording = false;\n\nvoid _reset() {\n    videoPath = null;\n    _changed(false);\n    _changedTimer("00:00");\n    _changedButtonVisibility(false);\n  }\n\n  void _changed(bool visibility) {\n    if (mounted) setState(() {\n      visibilityStop = visibility;\n    });\n  }\n\n  void _changedTimer(String time) {\n    if (mounted) setState(() {\n      timer = time;\n    });\n  }\n\n  void _changedButtonVisibility(bool visibility) {\n    if (mounted) setState(() {\n      visibilityButtons = visibility;\n    });\n  }\n\n  void _navigateAndDisplaySelection(BuildContext context) async {\n    final result = await Navigator.push(\n      context,\n      MaterialPageRoute(\n          builder: (context) => VideoPlayerScreen(\n              videoPath: videoPath.path,\n              applicationId: widget.applicationId,\n              name: widget.name,\n              dateTime: selectedDate,\n              isOpenSubsDashboard: widget.isOpenSubsDashboard)),\n    );\n\n    if (result) {\n      _reset();\n    }\n  }\n\n\n  @override\n  void initState() {\n    super.initState();\n    \n\n    WidgetsBinding.instance.addPostFrameCallback((_) =>\n        showSnackBar(\'User Validated Successfully! Welcome \' + widget.name));\n\n   \n    availableCameras().then((availableCameras) {\n      cameras = availableCameras;\n\n      if (cameras.length > 0) {\n      \n        for (int i = 0; i < cameras.length; i++) {\n          if (cameras[i].lensDirection == CameraLensDirection.front) {\n            if (mounted) setState(() {\n              selectedCameraIdx = i;\n            });\n          }\n        }\n\n        _onCameraSwitched(cameras[selectedCameraIdx]).then((void v) {});\n      }\n    }).catchError((err) {\n      print(\'Error: $err.code\\nError Message: $err.message\');\n    });\n  }\n\n\n  @override\n  Widget build(BuildContext context) {\n    var size = MediaQuery.of(context).size.width * (2 / 3);\n    return WillPopScope(\n      onWillPop: _onBackPressed,\n      child: Scaffold(\n          key: _scaffoldKey,\n          appBar: AppBarWidget(\n            title: \'Record Your Video\',\n              actions: [\n              IconButton(\n                  icon: Icon(\n                    Icons.call,\n                   \n                  ),\n                  onPressed: () {\n                    ConstantMethods.callToSupport();\n                  }),\n              AppBarLogo(),\n            ],\n          ),\n          body: Builder(builder: (BuildContext buildContext) {\n            scaffold = Scaffold.of(buildContext);\n            return Container(\n                   child: ListView(\n            \n              children: <Widget>[\n              \n           Center(\n                                  child: Container(\n                                width: size / 1.5,\n                                height: size / 1.5,\n                                \n                              Container(\n                                padding: EdgeInsets.all(5.0),\n                                color: Colors.grey[850],\n                                child: Text(\n                                    selectedDate != null ? selectedDate : "",\n                                    textAlign: TextAlign.start,\n                                    \n                              ),\n                            ],\n                          ),\n                        ))\n                    : Column(\n                        mainAxisAlignment: MainAxisAlignment.center,\n                        crossAxisAlignment: CrossAxisAlignment.center,\n                        children: <Widget>[\n                          VerticalSpacing(20.0),\n                          Padding(\n                              padding:\n                                  const EdgeInsets.only(left: 8.0, right: 8.0),\n                              child: Text(\n                                  \'Click on video icon to start the recording\',\n                                  textAlign: TextAlign.justify,\n                                 \n                          FlatButton(\n                         child: Text(\' Proceed for Recording \'),\n                            onPressed: () {\n                              if (mounted) setState(() {\n                                startRecording = true;\n                              });\n                            },\n                          ),\n                          VerticalSpacing(10.0),\n                          FlatButton(\n\n                            textColor: ThemeColors.colorPrimary,\n                            VerticalSpacing(20.0),\n                        ],\n                      ),\n                startRecording\n                    ? Padding(\n                        padding: const EdgeInsets.all(5.0),\n                        child: Row(\n                          mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                          children: <Widget>[\n                            _cameraTogglesRowWidget(),\n                          \n                            _captureControlRowWidget(),\n                            Expanded(\n                              child: Text("$timer",\n                                  textAlign: TextAlign.end,\n                                  style: TextStyle(\n                                      fontSize: Consts.fontSizeMedium)),\n                            ),\n                          ],\n                        ),\n                      )\n                    : new Container(),\n              \n                !visibilityButtons\n                    ? Column(\n                   \n                        children: [\n                          Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                              //alignment: Alignment.bottomRight,\n                              children: [\n                                IconButton(\n                                  icon: const Icon(Icons.info_outline,\n                                      size: 25.0),\n                                  color: ThemeColors.colorPrimary,\n                                  onPressed: () {\n                                    showDialog(\n                                      context: context,\n                                      builder: (BuildContext context) =>\n                                          MessageDialog(\n                                        title: "ImportantTips",\n                                        message: Languages.of(context)\n                                            .videoPreInstruction,\n                                      ),\n                                    );\n                                  \n                                  },\n                                ),\n                                ToggleButtons(\n                                  borderColor: ThemeColors.colorAccent,\n                                  fillColor: Colors.lightBlue[100],\n                                  borderWidth: 1,\n                                  selectedBorderColor: ThemeColors.colorAccent,\n                                  selectedColor: Colors.blue[900],\n                                  color: ThemeColors.colorPrimary,\n                                  borderRadius: BorderRadius.circular(10),\n                                  children: <Widget>[\n                                    Padding(\n                                      padding: const EdgeInsets.only(\n                                          left: 12.0, right: 8.0),\n                                      child: Text(\n                                        \'In English\',\n                                        textAlign: TextAlign.center,\n                                        style: TextStyle(\n                                            fontSize: Consts.fontSizeSmall),\n                                      ),\n                                    ),\n                                    Padding(\n                                      padding: const EdgeInsets.only(\n                                          left: 8.0, right: 8.0),\n                                      child: Text(\n                                        \'\xe0\xa4\xb9\xe0\xa4\xbf\xe0\xa4\x82\xe0\xa4\xa6\xe0\xa5\x80 \xe0\xa4\xae\xe0\xa5\x87\xe0\xa4\x82       \',\n                                        textAlign: TextAlign.center,\n                                        style: TextStyle(\n                                            fontSize: Consts.fontSizeSmall),\n                                      ),\n                                    ),\n                                  ],\n                                  onPressed: (int index) {\n                                    if(this.mounted) setState(() {\n                                      for (int i = 0;\n                                          i < isSelectedLanguage.length;\n                                          i++) {\n                                        if (i == index) {\n                                          isSelectedLanguage[i] = true;\n                                        } else {\n                                          isSelectedLanguage[i] = false;\n                                        }\n                                      }\n                                      if (isSelectedLanguage[0]) {\n                                        changeLanguage(context, \'en\');\n                                      } else if (isSelectedLanguage[1]) {\n                                        changeLanguage(context, \'hi\');\n                                      }\n                                    });\n                                  },\n                                  isSelected: isSelectedLanguage,\n                                )\n                              ]),\n                          VerticalSpacing(10.0),\n                        \n                          Padding(\n                              padding:\n                                  const EdgeInsets.only(left: 8.0, right: 8.0),\n                              child\n                    : Row(\n                        mainAxisAlignment: MainAxisAlignment.center,\n                        children: <Widget>[\n                          OutlineButton(\n                            padding: EdgeInsets.all(5.0),\n                            splashColor: Colors.blue[300],\n                            borderSide:\n                                BorderSide(color: ThemeColors.colorPrimary),\n                            child: Text(\' Retake Video \',\n                                style: TextStyle(\n                                    color: Colors.blue,\n                                    fontSize: Consts.fontSizeMedium)),\n                            onPressed: () {\n                              _reset();\n                            },\n                          ),\n                          HorizontalSpacing(10.0),\n                          FlatButton(\n                            padding: EdgeInsets.all(5.0),\n                            color: ThemeColors.colorPrimary,\n//            splashColor: Colors.greenAccent,\n                            textColor: ThemeColors.white,\n\n                            child: Text(\' Play Recording \',\n                                style:\n                                    TextStyle(fontSize: Consts.fontSizeMedium)),\n                            onPressed: () {\n                              if(videoPath!=null) {\n                                _navigateAndDisplaySelection(context);\n                              } else{\n                                //ConstantMethods.showToast("Technical exception with camera.");\n                                ConstantMethods.showToast("There is some issue in recording video right now, please try again later.");\n                                _onBackPressed();\n                              }\n                            },\n                          ),\n                        ],\n                      ),\n                VerticalSpacing(10.0),\n              ],\n            ));\n          })),\n    );\n  }\n\n  IconData _getCameraLensIcon(CameraLensDirection direction) {\n    switch (direction) {\n      case CameraLensDirection.back:\n        return Icons.camera_rear;\n      case CameraLensDirection.front:\n        return Icons.camera_front;\n      case CameraLensDirection.external:\n        return Icons.camera;\n      default:\n        return Icons.device_unknown;\n    }\n  }\n\n  // Display \'Loading\' text when the camera is still loading.\n  Widget _cameraPreviewWidget(var size) {\n    if (controller == null || !controller.value.isInitialized) {\n      return const Text(\n        \'Loading\',\n        style: TextStyle(\n          color: ThemeColors.white,\n          fontSize: 20.0,\n          fontWeight: FontWeight.w900,\n        ),\n      );\n    }\n\n    return Container(\n      width: size,\n      height: size,\n      child: ClipRect(\n        child: OverflowBox(\n          alignment: Alignment.center,\n          child: FittedBox(\n            fit: BoxFit.fitWidth,\n            child: Container(\n              width: size,\n              height: size / controller.value.aspectRatio,\n//              height: size / controller.value.aspectRatio,\n              child: CameraPreview(controller),\n\n              // this is my CameraPreview\n            ),\n          ),\n        ),\n      ),\n    );\n\n    \n  }\n\n  /// Display a row of toggle to select the camera (or a message if no camera is available).\n  Widget _cameraTogglesRowWidget() {\n    if (cameras == null) {\n      return Row();\n    }\n\n    CameraDescription selectedCamera =\n        cameras[selectedCameraIdx]; \n    CameraLensDirection lensDirection =\n        selectedCamera.lensDirection; \n    //CameraLensDirection lensDirection = CameraLensDirection.front;\n\n    return Expanded(\n      child: Align(\n        alignment: Alignment.centerLeft,\n        child: FlatButton.icon(\n            onPressed: controller != null && controller.value.isRecordingVideo\n                ? null\n                : _onSwitchCamera,\n            icon: Icon(_getCameraLensIcon(lensDirection)),\n            label: Text(\n                "${lensDirection.toString().substring(lensDirection.toString().indexOf(\'.\') + 1)}")),\n      ),\n    );\n  }\n\n  /// Display the control bar with buttons to record videos.\n  Widget _captureControlRowWidget() {\n    return Expanded(\n      child: Align(\n        alignment: Alignment.center,\n        child: Row(\n          mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n          mainAxisSize: MainAxisSize.max,\n          children: <Widget>[\n            IconButton(\n              icon: const Icon(Icons.videocam, size: 40.0),\n              color: ThemeColors.colorPrimary,\n              onPressed: controller != null &&\n                      controller.value.isInitialized &&\n                      !controller.value.isRecordingVideo &&\n                      videoPath == null\n                  ? _onRecordButtonPressed\n                  : null,\n            ),\n            IconButton(\n              icon: const Icon(Icons.stop, size: 40.0),\n              color: ThemeColors.red,\n              onPressed: controller != null &&\n                      controller.value.isInitialized &&\n                      controller.value.isRecordingVideo &&\n                      visibilityStop\n                  ? _onStopButtonPressed\n                  : null,\n            ),\n//                : new Container(),\n          ],\n        ),\n      ),\n    );\n  }\n\n  String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();\n\n  Future<void> _onCameraSwitched(CameraDescription description) async {\n\n      if (description == null) {\n        return;\n      }\n      if(!(controller != null && controller.value.isRecordingVideo)){\n        onNewCameraSelected(description);\n      }\n\n    \n  }\n\n  void onNewCameraSelected(CameraDescription cameraDescription) async {\n    if (controller != null) {\n      await controller.dispose();\n    }\n\n    controller = CameraController(\n      cameraDescription, ResolutionPreset.low\n    );\n\n    //controller = cameraController;\n\n    // If the controller is updated then update the UI.\n    controller.addListener(() {\n      if (mounted) setState(() {});\n      if (controller.value.hasError) {\n        Fluttertoast.showToast(\n            msg: \'Camera error ${controller.value.errorDescription}\',\n            toastLength: Toast.LENGTH_SHORT,\n            gravity: ToastGravity.CENTER,\n            timeInSecForIosWeb: 1,\n            backgroundColor: ThemeColors.red,\n            textColor: ThemeColors.white);\n      }\n    });\n\n    try {\n      await controller.initialize();\n    } on CameraException catch (e) {\n      _showCameraException(e);\n    }\n\n    if (mounted) {\n      setState(() {});\n    }\n  }\n\n  void _onSwitchCamera() {\n    selectedCameraIdx =\n        selectedCameraIdx < cameras.length - 1 ? selectedCameraIdx + 1 : 0;\n    CameraDescription selectedCamera = cameras[selectedCameraIdx];\n\n    _onCameraSwitched(selectedCamera);\n\n    if (mounted) setState(() {\n      selectedCameraIdx = selectedCameraIdx;\n    });\n  }\n\n  void _onRecordButtonPressed() {\n    _startVideoRecording().then((_) {\n      /*if (mounted) setState(() {});*/\n      //if (filePath != null) {\n      final df = new DateFormat(\'dd-MM-yyyy hh:mm a\');\n      String date = df.format(new DateTime.now());\n\n      if (mounted) setState(() {\n//          selectedDate = date1.replaceAll("/", "-");\n        selectedDate = date;\n      });\n\n      Fluttertoast.showToast(\n          msg: \'Recording video started\',\n          toastLength: Toast.LENGTH_SHORT,\n          gravity: ToastGravity.CENTER,\n          timeInSecForIosWeb: 1,\n          backgroundColor: ThemeColors.grey,\n          textColor: ThemeColors.white);\n      // }\n    });\n  }\n\n  void _onStopButtonPressed() {\n    if (cd.isRunning) {\n      cd.cancel();\n    }\n\n    _stopVideoRecording().then((file) {\n      if (mounted) setState(() {});\n      if (file != null) {\n        showInSnackBar(\'Video recorded to ${file.path}\');\n        videoPath = file;\n      }\n\n    });\n  }\n\n  Future<void> _star