gpt4 book ai didi

flutter - 使用相机包授予权限会在出现异常时暂停调试器

转载 作者:IT王子 更新时间:2023-10-29 06:42:32 29 4
gpt4 key购买 nike

我正在使用 camera一个简单功能的包。我主要关注 example提供的包裹。当我打开相机小部件页面时,包会自动提示提供相机和麦克风的权限。单击允许这两个权限后,调试器暂停并出现异常:

Exception has occurred.
FlutterError (A CameraController was used after being disposed.
Once you have called dispose() on a CameraController, it can no longer be used.).

这是所需的代码:

class CameraPage extends StatefulWidget {
@override
_CameraPageState createState() => _CameraPageState();
}

class _CameraPageState extends State<CameraPage>
with WidgetsBindingObserver {
CameraController _controller;
List<CameraDescription> _availableCameras;
...

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_initialize();
}

Future<void> _initialize() async {
await _getCameras();
_controller = CameraController(_availableCameras[0], ResolutionPreset.high);
await _controller.initialize();
if (!mounted) {
return;
}
setState(() {});
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.inactive) {
_controller?.dispose();
} else if (state == AppLifecycleState.resumed) {
if (_controller != null) {
_setCurrentCamera(_controller.description);
}
}
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_controller.dispose();
super.dispose();
}


Future<List<CameraDescription>> _getCameras() async {
List<CameraDescription> camDescriptions;
camDescriptions = await availableCameras();

_availableCameras = camDescriptions;
return camDescriptions;
}

@override
Widget build(BuildContext context) {
...
}


Future<void> _setCurrentCamera(CameraDescription cameraDescription) async {
if (_controller != null) {
await _controller.dispose();
}
_controller = CameraController(
cameraDescription,
ResolutionPreset.high,
enableAudio: false,
);

// If the _controller is updated then update the UI.
_controller.addListener(() {
if (mounted) setState(() {});

if (_controller.value.hasError) {
print('Camera error ${_controller.value.errorDescription}');
}
});

try {
await _controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}

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

void _switchCamera() {
if (_controller != null && !_controller.value.isRecordingVideo) {
CameraLensDirection direction = _controller.description.lensDirection;
CameraLensDirection required = direction == CameraLensDirection.front
? CameraLensDirection.back
: CameraLensDirection.front;
for (CameraDescription cameraDescription in _availableCameras) {
if (cameraDescription.lensDirection == required) {
_setCurrentCamera(cameraDescription);
return;
}
}
}
}


void _showCameraException(CameraException e) {
String errorText = 'Error: ${e.code}\nError Message: ${e.description}';
print(errorText);
}

}

调试器将异常指向此处:

  Future<void> _initialize() async {
await _getCameras();
_controller = CameraController(_availableCameras[0], ResolutionPreset.high);
//-------------HERE------------------
await _controller.initialize();
if (!mounted) {
return;
}
setState(() {});
}

一旦我恢复调试器并尝试再次打开这个相机页面,就没有错误/异常了。它仅在第一次接受权限后发生。

最佳答案

可能真正的罪魁祸首是 didChangeAppLifecycleState

一旦调用 await _controller.initialize(); 并显示权限对话框,生命周期事件 AppLifecycleState.inactive 将被触发,当前 Controller 将根据您的设置进行处理didChangeAppLifecycleState 中的代码,因此当应用程序在授予权限后恢复并尝试继续时,它会抛出错误。

尝试删除

if (state == AppLifecycleState.inactive) {
_controller?.dispose();
}

或者有一个局部变量来检查是否初始化并在初始化时忽略处置

Future<void> _initialize() async {
await _getCameras();
_controller = CameraController(_availableCameras[0], ResolutionPreset.high);
_initializing = true;
await _controller.initialize();
_initializing = false;
if (!mounted) {
return;
}
setState(() {});
}

并且在 didChangeAppLifecycleState

if (state == AppLifecycleState.inactive && !_initializing) {
_controller?.dispose();
}

编辑:

可能是,我想我发现了问题,实际问题是 didChangeAppLifecycleState 正如预期的那样,didChangeAppLifecycleState 中的 if 子句,如果事实证明是真的,_controller 正在处理,如果不是,_setCurrentCamera 只是处理任何事件的 Controller 。因此,当您调用初始化并等待权限时,在权限 future 解决之前,_controller 将由 didChangeAppLifecycleState 处理。

我的解决方案只需进行简单的更改即可。将您的 initState 更改为

@override
void initState() {
super.initState();
_initializing = true; // set to true
WidgetsBinding.instance.addObserver(this);
_initialize();
}

改变你的 _initialize 函数使 _initializing = false 像初始化一样,

Future<void> _initialize() async {
await _getCameras();
_controller = CameraController(_availableCameras[0],ResolutionPreset.high);
await _controller.initialize();
_initializing = false; // set to false
if (!mounted) {
return;
}
setState(() {});
}

和你的 didChangeAppLifecycleState

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if(_initializing){
return;
}
if (state == AppLifecycleState.inactive) {
_controller?.dispose();
} else if (state == AppLifecycleState.resumed) {
if (_controller != null) {
_setCurrentCamera(_controller.description);
}
}
}

这样,如果 _initializing == true 你永远不会释放当前 Controller 。


希望对您有所帮助!

关于flutter - 使用相机包授予权限会在出现异常时暂停调试器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57003213/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com