initCameras method

Future<void> initCameras([
  1. CameraDescription? cameraDescription
])

Initialize cameras instances. 初始化相机实例

Implementation

Future<void> initCameras([CameraDescription? cameraDescription]) async {
  // Save the current controller to a local variable.
  final CameraController? c = innerController;
  // Dispose at last to avoid disposed usage with assertions.
  if (c != null) {
    innerController = null;
    await c.dispose();
  }
  // Then request a new frame to unbind the controller from elements.
  safeSetState(() {
    maxAvailableZoom = 1;
    minAvailableZoom = 1;
    currentZoom = 1;
    baseZoom = 1;
    // Meanwhile, cancel the existed exposure point and mode display.
    exposureModeDisplayTimer?.cancel();
    exposurePointDisplayTimer?.cancel();
    lastExposurePoint.value = null;
    if (currentExposureOffset.value != 0) {
      currentExposureOffset.value = 0;
    }
  });
  // **IMPORTANT**: Push methods into a post frame callback, which ensures the
  // controller has already unbind from widgets.
  ambiguate(WidgetsBinding.instance)?.addPostFrameCallback((_) async {
    // When the [cameraDescription] is null, which means this is the first
    // time initializing cameras, so available cameras should be fetched.
    if (cameraDescription == null) {
      cameras = await availableCameras();
    }

    // After cameras fetched, judge again with the list is empty or not to
    // ensure there is at least an available camera for use.
    if (cameraDescription == null && cameras.isEmpty) {
      handleErrorWithHandler(
        CameraException(
          'No CameraDescription found.',
          'No cameras are available in the controller.',
        ),
        pickerConfig.onError,
      );
    }

    initFlashModesForCameras();
    final int preferredIndex = cameras.indexWhere(
      (CameraDescription e) =>
          e.lensDirection == pickerConfig.preferredLensDirection,
    );
    final int index;
    if (preferredIndex != -1 && c == null) {
      index = preferredIndex;
      currentCameraIndex = preferredIndex;
    } else {
      index = currentCameraIndex;
    }
    // Initialize the controller with the given resolution preset.
    final CameraController newController = CameraController(
      cameraDescription ?? cameras[index],
      pickerConfig.resolutionPreset,
      enableAudio: enableAudio,
      imageFormatGroup: pickerConfig.imageFormatGroup,
    );

    try {
      final Stopwatch stopwatch = Stopwatch()..start();
      await newController.initialize();
      stopwatch.stop();
      realDebugPrint("${stopwatch.elapsed} for controller's initialization.");
      // Call recording preparation first.
      if (shouldPrepareForVideoRecording) {
        stopwatch
          ..reset()
          ..start();
        await newController.prepareForVideoRecording();
        stopwatch.stop();
        realDebugPrint("${stopwatch.elapsed} for recording's preparation.");
      }
      // Then call other asynchronous methods.
      stopwatch
        ..reset()
        ..start();
      await Future.wait(
        <Future<void>>[
          if (pickerConfig.lockCaptureOrientation != null)
            newController
                .lockCaptureOrientation(pickerConfig.lockCaptureOrientation),
          newController
              .getExposureOffsetStepSize()
              .then((double value) => exposureStep = value),
          newController
              .getMaxExposureOffset()
              .then((double value) => maxAvailableExposureOffset = value),
          newController
              .getMinExposureOffset()
              .then((double value) => minAvailableExposureOffset = value),
          newController
              .getMaxZoomLevel()
              .then((double value) => maxAvailableZoom = value),
          newController
              .getMinZoomLevel()
              .then((double value) => minAvailableZoom = value),
          if (pickerConfig.preferredFlashMode != FlashMode.auto)
            newController.setFlashMode(pickerConfig.preferredFlashMode),
        ],
        eagerError: true,
      );
      stopwatch.stop();
      realDebugPrint("${stopwatch.elapsed} for config's update.");
      innerController = newController;
    } catch (e, s) {
      handleErrorWithHandler(e, pickerConfig.onError, s: s);
    } finally {
      safeSetState(() {});
    }
  });
}