Flutter-相机内存问题

时间:2018-08-22 12:35:54

标签: dart flutter

由于VS代码无法识别我的手机,因此我尝试使用相机插件拍摄视频,并且在Xcode中运行项目以运行真实设备时。 问题是,即使我打电话给dispose(),应用程序崩溃,我也将摄像机前后切换到5次以上(少于10次)。另外,在录制视频和播放录制的视频时,几乎会发生50%到60%的崩溃。
Xcode说

  

来自调试器的消息:由于内存问题而终止

我看到flutter没有任何内存泄漏,我们也不需要关心内存管理。
那为什么会这样呢?
我缺少什么东西吗? 有人知道发生了什么吗?

代码:

 class CameraScreenState extends State<CameraScreen>
    with TickerProviderStateMixin {
  List<CameraDescription> _cameraDescriptions;
  CameraController _cameraController;
  VideoPlayerController _videoController;
  AnimationController _animationController;
  String imagePath;
  String videoPath;
  VoidCallback videoPlayerListener;
  bool _isSelfie = false;
  bool _isRecorded = false;
  bool _isRecording = false;
  bool _isReady = false;

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

  Future<void> _setupCameras() async {
    try {
      _cameraDescriptions = await availableCameras();
      _cameraController = new CameraController(_cameraDescriptions[0], ResolutionPreset.high);
      await _cameraController.initialize();
    } on CameraException catch (_) {
      // do something on error.
    }
    if (!mounted) return;
    setState(() {
      _isReady = true;
    });
     _animationController = new AnimationController(
        vsync: this,
        duration: new Duration(seconds: 15),
      );
  }

   @override
  void deactivate() {
    _videoController?.setVolume(0.0);
    _videoController?.removeListener(videoPlayerListener);
    super.deactivate();
  }

  @override
  void dispose() {
    _cameraController?.dispose();
    _animationController?.dispose();
    _videoController?.dispose();
    super.dispose();
  }

  String timestamp() => new DateTime.now().millisecondsSinceEpoch.toString();

  Future _changeDirection(CameraDescription cameraDescription) async {

      await _cameraController.dispose().then((_) async {

          _cameraController =
        new CameraController(cameraDescription, ResolutionPreset.high);

    _cameraController.addListener(() {
      if (mounted) setState(() {});
      if (_cameraController.value.hasError) {
        print(_cameraController.value.errorDescription);
      }
    });

    try {
      await _cameraController.initialize();
    } on CameraException catch (e) {
      print(e);
    }

    if (mounted) {
      setState(() {});
    }


      });


  }

   _toSelfie() {
      _changeDirection(_cameraDescriptions[1]);
  }

  _toForward() {
     _changeDirection(_cameraDescriptions[0]);
  }

  void onVideoRecordButtonPressed() {
    startVideoRecording().then((String filePath) {
      if (mounted) setState(() {});
      if (filePath != null) print('Saving video to $filePath');
    });
  }

  void onStopButtonPressed() {
    stopVideoRecording().then((_) {
      if (mounted) setState(() {});
      print('Video recorded to: $videoPath');
    });
  }

  Future<String> startVideoRecording() async {
    if (!_cameraController.value.isInitialized) {
      print('Error: select a camera first.');
      return null;
    }

    final Directory extDir = await getTemporaryDirectory();
    final String dirPath = '${extDir.path}/Movies/flutter_test';
    await new Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/${timestamp()}.mp4';

    if (_cameraController.value.isRecordingVideo) {
      // A recording is already started, do nothing.
      return null;
    }

    try {
      videoPath = filePath;
      await _cameraController.startVideoRecording(filePath).then((_) async {
        final animation = _animationController.forward(from: 0.0);
        await animation.then((_) {
          setState(() {
             onStopButtonPressed();
            _isRecorded = true;
          });
        });
      });
    } on CameraException catch (e) {
      print(e);
      return null;
    }
    return filePath;
  }

  Future<void> stopVideoRecording() async {
    if (!_cameraController.value.isRecordingVideo) {
      return null;
    }

    try {
      await _cameraController.stopVideoRecording();
    } on CameraException catch (e) {
      print(e);
      return null;
    }

    await _startVideoPlayer();
  }

  Future<void> _startVideoPlayer() async {
    final VideoPlayerController vcontroller =
        new VideoPlayerController.file(new File(videoPath));
    videoPlayerListener = () {
      if (_videoController != null && _videoController.value.size != null) {
        // Refreshing the state to update video player with the correct ratio.
        if (mounted) setState(() {});
        _videoController.removeListener(videoPlayerListener);
      }
    };
    vcontroller.addListener(videoPlayerListener);
    await vcontroller.setLooping(true);
    await vcontroller.initialize();
    await _videoController?.dispose();
    if (mounted) {
      setState(() {
        imagePath = null;
        _videoController = vcontroller;
      });
    }
    await vcontroller.play();
  }

  _startVideoRecordingCoountDown() {
    onVideoRecordButtonPressed();
  }

  _stopVideoRecordingCountDown() {
    setState(() {
      _animationController.stop();
      onStopButtonPressed();
      _isRecorded = true;
    });
  }


  @override
  Widget build(BuildContext context) {
      if (!_isReady) {
      return new Container(
          color: Colors.black,
          child: new Center(child: new CircularProgressIndicator()));
    }
    return new Scaffold(
      backgroundColor: Colors.black,
      body: !_isRecorded
          ? new Stack(
              children: <Widget>[
                new AspectRatio(
                  aspectRatio: _cameraController.value.aspectRatio,
                  child: new CameraPreview(_cameraController),
                ),
                !_isRecording
                    ? new Align(
                        alignment: Alignment.topLeft,
                        child: new Container(
                          child: new FloatingActionButton(
                            heroTag: 'start',
                            backgroundColor: Colors.black.withOpacity(0.001),
                            elevation: 50.0,
                            child: new Center(
                                child: new Icon(Icons.clear, size: 28.0)),
                            onPressed: () {
                              Navigator.of(context).pop();
                            },
                          ),
                        ),
                      )
                    : new Container(),
                new Align(
                  alignment: new Alignment(0.0, 1.0),
                  child: new Container(
                    margin: const EdgeInsets.only(bottom: 10.0),
                    child: new FloatingActionButton(
                      elevation: 30.0,
                      backgroundColor: Colors.white,
                      foregroundColor: Colors.amber,
                      child: _animationController.isAnimating
                          ? new Countdown(
                              animation: new StepTween(
                                begin: 16,
                                end: 0,
                              ).animate(_animationController),
                            )
                          : new Icon(Icons.play_arrow),
                      onPressed: () {
                        setState(() {
                          _isRecording = true;
                        });
                        !_animationController.isAnimating
                            ? _startVideoRecordingCoountDown()
                            : _stopVideoRecordingCountDown();
                      },
                    ),
                  ),
                ),
                !_isRecording
                    ? new Align(
                        alignment: Alignment.bottomRight,
                        child: new Container(
                          margin:
                              const EdgeInsets.only(right: 15.0, bottom: 10.0),
                          child: new FloatingActionButton(
                            elevation: 50.0,
                            backgroundColor: Colors.black.withOpacity(0.001),
                            child: new Icon(Icons.cached, size: 35.0),
                            onPressed: () {
                              setState(() {
                                _isSelfie ? _toForward() : _toSelfie();
                                _isSelfie
                                    ? _isSelfie = false
                                    : _isSelfie = true;
                              });
                            },
                          ),
                        ),
                      )
                    : new Container(),
              ],
              fit: StackFit.expand,
            )
          : _videoController == null
              ? new Container(
                  color: Colors.black,
                  child: new Center(child: new CircularProgressIndicator()))
              : _videoController.value.size != null
                  ? new AspectRatio(
                      aspectRatio: _videoController.value.aspectRatio,
                      child: new VideoPlayer(_videoController),
                    )
                  : new Container(
                      width: MediaQuery.of(context).size.width,
                      height: MediaQuery.of(context).size.height,
                      child: new VideoPlayer(_videoController)),
    );
  }
}

0 个答案:

没有答案