dart 使相机活动在Flutter中加载得更快

gupuwyp2  于 12个月前  发布在  Flutter
关注(0)|答案(1)|浏览(100)

我有这个barcodeScannerView。我如何设置它,使相机将立即加载,就像在这个video
即使我不检查权限,加载摄像头也需要2秒,它显示一个白色屏幕,然后一秒黑色,然后是摄像头,这是一个糟糕的用户体验。我希望用户有一个即时的体验,就像在所附的视频。

class BarcodeScannerView extends StatefulWidget {
      @override
      State<BarcodeScannerView> createState() => _BarcodeScannerViewState();
    }
    
    class _BarcodeScannerViewState extends State<BarcodeScannerView> {
      final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
      final BarcodeScanner _barcodeScanner = BarcodeScanner();
      bool _canProcess = true;
      bool _isBusy = false;
      CustomPaint? _customPaint;
      String? _text;
      bool _hasNavigated = false;
      var _cameraLensDirection = CameraLensDirection.back;
      late StreamController<PermissionStatus?> _permissionStatusController;
    
      @override
      void initState() {
        super.initState();
        _permissionStatusController = StreamController<PermissionStatus?>();
        _checkAndRequestCameraPermission();
      }
    
      @override
      void dispose() {
        _canProcess = false;
        _barcodeScanner.close();
        _permissionStatusController.close();
        super.dispose();
      }
    
      Future<void> _checkAndRequestCameraPermission() async {
        PermissionStatus status = await Permission.camera.status;
        if (!status.isGranted) {
          status = await Permission.camera.request();
        }
        _permissionStatusController.add(status);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          key: _scaffoldKey,
          body: StreamBuilder<PermissionStatus?>(
            stream: _permissionStatusController.stream,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.active) {
                if (snapshot.data == PermissionStatus.granted) {
                  return _buildCameraView();
                } else {
                  return Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text('הרשאות המצלמה נדחו'),
                        SizedBox(height: 16),
                        ElevatedButton(
                          onPressed: () => openAppSettings(),
                          child: Text('אפשר הרשאות מצלמה'),
                        ),
                      ],
                    ),
                  );
                }
              } else {
                return Center(child: CircularProgressIndicator());
              }
            },
          ),
        );
      }
    
      Widget _buildCameraView() {
        return DetectorView(
          title: 'Barcode Scanner',
          customPaint: _customPaint,
          text: _text,
          onImage: _checkAndProcessImage,
          initialCameraLensDirection: _cameraLensDirection,
          onCameraLensDirectionChanged: (value) => _cameraLensDirection = value,
        );
      }
    
      Future<void> _checkAndProcessImage(InputImage inputImage) async {
        if (!_canProcess) return;
        if (_isBusy) return;
    
    
        // Camera permission is granted, proceed to process the image
        _isBusy = true;
        setState(() {
          _text = '';
        });
    
        final barcodes = await _barcodeScanner.processImage(inputImage);
    
        if (inputImage.metadata?.size != null &&
            inputImage.metadata?.rotation != null) {
          for (final barcode in barcodes) {
            print('Scanned Barcode: ${barcode.rawValue}');
    
            // Navigate to the new screen with the barcode value
            if (!_hasNavigated &&
                (barcode.format == BarcodeFormat.upca ||
                    barcode.format == BarcodeFormat.ean13 ||
                    barcode.format == BarcodeFormat.upce)) {
              _hasNavigated = true;
              HapticFeedback.vibrate();
    
              showModalBottomSheet(
                context: _scaffoldKey.currentContext!,
                isScrollControlled: true,
                builder: (context) => DraggableScrollableSheet(
                  expand: false,
                  initialChildSize: 0.3,
                  maxChildSize: 0.85,
                  builder: (context, scrollController) => ClipRRect(
                    borderRadius: BorderRadius.circular(16.0),
                    child: Scaffold(
                      body: ProductDetailsView(
                        barcodeValue: barcode.rawValue ?? '',
                        scrollController: scrollController,
                      ),
                    ),
                  ),
                ),
              ).whenComplete(() {
                ScaffoldMessenger.of(context).removeCurrentSnackBar();
                _hasNavigated = false;
              });
            }
          }
    
          final painter = BarcodeDetectorPainter(
            barcodes,
            inputImage.metadata!.size,
            inputImage.metadata!.rotation,
            _cameraLensDirection,
          );
          _customPaint = CustomPaint(painter: painter);
        } else {
          String text = 'Barcodes found: ${barcodes.length}\n\n';
          for (final barcode in barcodes) {
            text += 'Barcode: ${barcode.rawValue}\n\n';
          }
          _text = text;
          _customPaint = null;
        }
    
        _isBusy = false;
        if (mounted) {
          setState(() {});
        }
      }
    }

字符串
下面是cameraViewdetectorView的代码
我从主页bottomNavigationBar调用barcodeScannerView,如下所示:

class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _currentIndex = 0;
      final List<Widget> _screens = [
        BarcodeScannerView(),
        HistoryScreen(),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: _screens[_currentIndex],
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: _currentIndex,
            onTap: (index) {
              setState(() {
                _currentIndex = index;
              });
            },
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.barcode_reader),
                label: 'Scan,
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.history),
                label: 'History,
              ),
            ],
          ),
        );
      }
    }

igetnqfo

igetnqfo1#

将摄像头初始化逻辑移到小部件生命周期的稍后阶段,这样它就不会影响初始构建。
您可以在BarcodeScannerView的initState中初始化摄像头,甚至更晚,例如,当用户点击扫描按钮时。

class _BarcodeScannerViewState extends State<BarcodeScannerView> {
  // ...

  @override
  void initState() {
    super.initState();
    _permissionStatusController = StreamController<PermissionStatus?>();
    // Do not initialize the camera here
  }

  Future<void> _initializeCamera() async {
    // Initialize the camera here
  }

  // ...

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: StreamBuilder<PermissionStatus?>(
        stream: _permissionStatusController.stream,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.active) {
            if (snapshot.data == PermissionStatus.granted) {
              return _buildCameraView();
            } else {
              return Center(
                child: Column(
                  // ...
                ),
              );
            }
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }

  Widget _buildCameraView() {
    return GestureDetector(
      onTap: () => _initializeCamera(),
      child: // ... Your camera view widget
    );
  }

  // ...
}

字符串
考虑在后台初始化相机,同时显示启动画面或加载指示器。

class _MyHomePageState extends State<MyHomePage> {
  // ...

  Future<void> _initializeCameraInBackground() async {
    // Initialize the camera here
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _currentIndex == 0
          ? FutureBuilder(
              future: _initializeCameraInBackground(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  return _screens[_currentIndex];
                } else {
                  return SplashScreen(); // Replace with your splash screen widget
                }
              },
            )
          : _screens[_currentIndex],
      // ...
    );
  }
}

  • 通过进行这些更改,您应该能够通过更快的相机加载时间提供更好的用户体验。请记住在不同设备上测试性能,以确保一致的体验。*

相关问题