#flutter #dart #exception #error-handling #solution
Вопрос:
Эй, ребята, у меня следующая проблема, и я надеюсь, что кто-нибудь сможет мне помочь: я пытаюсь включить камеру в свое приложение flutter, используя следующий код:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
class Route02 extends StatefulWidget {
@override
CameraState createState() => CameraState();
}
class CameraState extends State<Route02> {
late List<CameraDescription> cameras;
late CameraController _controller;
bool isReady = false;
@override
void initState() {
super.initState();
setupCameras();
}
Future<void> setupCameras() async {
try {
cameras = await availableCameras();
_controller = new CameraController(cameras[0], ResolutionPreset.ultraHigh);
await _controller.initialize();
} on CameraException catch () {
setState(() {
isReady = false;
});
}
setState(() {
isReady = true;
});
}
Widget build(BuildContext context) {
if (!isReady amp;amp; !_controller.value.isInitialized) {
return Container();
}
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: CameraPreview(_controller));
}
}
При доступе к части камеры в приложении можно увидеть следующую ошибку, и после этого камера все равно запустится:
Ошибка поздней инициализации: поле «контроллер» не было инициализировано.
Я уже пытался добавить метод whenComplete() и использовал?, но это тоже не сработало.
У кого-нибудь есть идея?
Комментарии:
1. Где
controller
объявлено? Есть ли какая-то связь междуcontroller
и_controller
тем, что вы не предусмотрели?2. @jamesdlin это то же самое, что было просто моей ошибкой, я уже исправил это, но это все та же ошибка.
3. Вам удалось это исправить?
Ответ №1:
Я думаю, проблема в том, что вы запускаете » setupCameras ()», который является асинхронным внутри метода » initState ()», которого нет. Попробуйте это:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
class Route02 extends StatefulWidget {
@override
CameraState createState() => CameraState();
}
class CameraState extends State<Route02> {
late List<CameraDescription> cameras;
late CameraController _controller;
Future<void> setupCameras() async {
try {
cameras = await availableCameras();
_controller = new CameraController(cameras[0], ResolutionPreset.ultraHigh);
await controller.initialize();
}
Widget build(BuildContext context) {
return FutureBuilder(
future: setupCameras(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: CameraPreview(_controller)
);
};
);
}
}
Комментарии:
1. Спасибо, я пытался, но это все та же ошибка. Я понятия не имею, почему…
Ответ №2:
У меня та же проблема, и я не могу найти идеального решения.
- Я не думаю, что FutureBuilder будет работать в этом случае. Вам также нужно разобраться с утилизацией. Похоже, это не то, что вы можете сделать с помощью FutureBuilder.
- Реальность такова, что вы, возможно, не сможете успешно инициализировать CameraController. По каким-либо причинам getCameras ничего вам не возвращает. Это означает, что всегда возможно, что ваш контроллер камеры может быть равен нулю. Таким образом, попытка настроить код таким образом, чтобы он был ненулевым типом, неправильна.
В итоге я просто изменил его на тип, допускающий обнуление, и при необходимости выполнял проверку на обнуление. ИМО, дарт далеко пойдет ради нулевой безопасности. Это только усложняет ситуацию. Мне нравится, как Python обрабатывает nullable, используя None.
CameraController? _controller;
Ответ №3:
Я вижу две проблемы:
setupCameras()
делает:
try { // ... } on CameraException catch () { setState(() { isReady = false; }); } setState(() { isReady = true; });
это означает, что если a
CameraException
будет брошен,isReady
будет установленоfalse
значение, но затем сразу же будет установлено значениеtrue
.build
Функция выполняет:
if (!isReady amp;amp; !_controller.value.isInitialized) { return Container(); }
Если
isReady
значение равно false (что, я полагаю, должно указывать на то, что_controller
оно еще не инициализировано), то вы дополнительно проверяете_controller.value.isInitialized
, даже если_controller
оно еще не инициализировано. Вы, вероятно, хотите||
вместоamp;amp;
этого .
В качестве альтернативы, подумайте о том, чтобы просто сделать _controller
nullable вместо late
. Если вам все равно нужно проверить логический флаг ( isReady
) перед доступом _controller
, это не лучше, чем сделать _controller
nullable и проверять _controller != null
напрямую, что более просто и менее подвержено ошибкам.