Flutter-将getter'value'调用为null

我正在尝试将当前选择的摄像机保存到SharedPreferences。当应用重新启动时,我希望最初使用同一台相机。如果用户切换到其他摄像机,该摄像机将被保存。

当我在initState中包含以下代码时,我得到“在null上调用getter'值'”。错误信息。同样,红色/黄色错误消息会显示并在相机开始工作之前迅速消失。

  @override
  void initState() {
    try {
      SharedPreferencesHelper prefs = SharedPreferencesHelper();
      prefs.getcameraSelected().then((String answer) {
        if (answer != null) {
          if (answer == 'back') {
            onCameraSelected(widget.cameras[0]);
          } else {
            onCameraSelected(widget.cameras[1]);
          }
        } else {
          print('answer is null');
          onCameraSelected(widget.cameras[1]);
        }
      });
    } catch (e) {
      print(e.toString());
    }
    super.initState();
  }

如果我将initState改回原始状态,一切都会按预期进行

  @override
  void initState() {
    try {
      onCameraSelected(widget.cameras[0]);
    } catch (e) {
      print(e.toString());
    }
    super.initState();
  }

以下是CameraHomeScreen.dart文件的完整代码:

import 'dart:async';
import 'dart:io';

import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class CameraHomeScreen extends StatefulWidget {
  List<CameraDescription> cameras;

  CameraHomeScreen(this.cameras);

  @override
  State<StatefulWidget> createState() {
    return _CameraHomeScreenState();
  }
}

class _CameraHomeScreenState extends State<CameraHomeScreen> {
  String imagePath;
  bool _toggleCamera = false;
  String _currentCamera = 'back';
  Cameracontroller controller;

  @override
  void initState() {
    try {
      SharedPreferencesHelper prefs = SharedPreferencesHelper();
      prefs.getcameraSelected().then((String answer) {
        if (answer != null) {
          print('here');
          print(answer);
          if (answer == 'back') {
            onCameraSelected(widget.cameras[0]);
          } else {
            onCameraSelected(widget.cameras[1]);
          }
        } else {
          print('answer is null');
          onCameraSelected(widget.cameras[1]);
        }
      });
    } catch (e) {
      print(e.toString());
    }
    super.initState();
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.cameras.isEmpty) {
      return Container(
        alignment: Alignment.center,padding: EdgeInsets.all(16.0),child: Text(
          'No Camera Found',style: TextStyle(
            fontSize: 16.0,color: Colors.white,),);
    }

    if (!controller.value.isInitialized) {
      return Container();
    }

    return AspectRatio(
      aspectRatio: controller.value.aspectRatio,child: Container(
        child: Stack(
          children: <Widget>[
            CameraPreview(controller),Align(
              alignment: Alignment.bottomCenter,child: Container(
                width: double.infinity,height: 120.0,padding: EdgeInsets.all(20.0),color: Color.fromRGBO(00,00,0.7),child: Stack(
                  children: <Widget>[
                    Align(
                      alignment: Alignment.center,child: Material(
                        color: Colors.transparent,child: InkWell(
                          borderRadius: BorderRadius.all(Radius.circular(50.0)),onTap: () {
                            _captureImage();
                          },child: Container(
                            padding: EdgeInsets.all(4.0),child: Image.asset(
                              'assets/images/ic_shutter_1.png',width: 72.0,height: 72.0,Align(
                      alignment: Alignment.centerRight,onTap: () {
                            if (!_toggleCamera) {
                              SharedPreferencesHelper prefs =
                                  SharedPreferencesHelper();
                              prefs.setCameraSelected('front');
                              onCameraSelected(widget.cameras[1]);
                              setState(() {
                                _toggleCamera = true;
                              });
                            } else {
                              SharedPreferencesHelper prefs =
                                  SharedPreferencesHelper();
                              prefs.setCameraSelected('back');
                              onCameraSelected(widget.cameras[0]);
                              setState(() {
                                _toggleCamera = false;
                              });
                            }
                          },child: Image.asset(
                              'assets/images/ic_switch_camera_3.png',color: Colors.grey[200],width: 42.0,height: 42.0,],);
  }

  void onCameraSelected(CameraDescription cameraDescription) async {
    if (controller != null) await controller.dispose();
    controller = Cameracontroller(cameraDescription,ResolutionPreset.medium);

    controller.addListener(() {
      if (mounted) setState(() {});
      if (controller.value.hasError) {
        showMessage('Camera Error: ${controller.value.errorDescription}');
      }
    });

    try {
      await controller.initialize();
    } on CameraException catch (e) {
      showException(e);
    }

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

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

  void _captureImage() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
        });
        if (filePath != null) {
          showMessage('Picture saved to $filePath');
          setCameraResult();
        }
      }
    });
  }

  void setCameraResult() {
    Navigator.pop(context,imagePath);
  }

  Future<String> takePicture() async {
    if (!controller.value.isInitialized) {
      showMessage('Error: select a camera first.');
      return null;
    }
    final Directory extDir = await getapplicationDocumentsDirectory();
    final String dirPath = '${extDir.path}/FlutterDevs/Camera/Images';
    await new Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/${timestamp()}.jpg';

    if (controller.value.isTakingPicture) {
      // A capture is already pending,do nothing.
      return null;
    }

    try {
      await controller.takePicture(filePath);
    } on CameraException catch (e) {
      showException(e);
      return null;
    }
    return filePath;
  }

  void showException(CameraException e) {
    logError(e.code,e.description);
    showMessage('Error: ${e.code}\n${e.description}');
  }

  void showMessage(String message) {
    print(message);
  }

  void logError(String code,String message) =>
      print('Error: $code\nmessage: $message');
}

class SharedPreferencesHelper {
  ///
  /// Instantiation of the SharedPreferences library
  ///
  final String _nameKey = "cameraSelected";

  /// ------------------------------------------------------------
  /// Method that returns the user decision on sorting order
  /// ------------------------------------------------------------
  Future<String> getcameraSelected() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    return prefs.getString(_nameKey) ?? 'name';
  }

  /// ----------------------------------------------------------
  /// Method that saves the user decision on sorting order
  /// ----------------------------------------------------------
  Future<bool> setCameraSelected(String value) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    return prefs.setString(_nameKey,value);
  }
}
kakyomuyu 回答:Flutter-将getter'value'调用为null

您可以在下面复制粘贴运行完整代码
SharedPreferences之前使用runApp(MyApp());
class CameraHomeScreeninitCamera添加参数
并像这样CameraHomeScreen(cameras,initCamera)使用它,

代码段

String initCamera;
List<CameraDescription> cameras;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  SharedPreferences pre = await SharedPreferences.getInstance();
  //await prefs.setString("cameraSelected","front");
  initCamera = await pre.getString("cameraSelected");
  print('initCamera ${initCamera}');
  runApp(MyApp());
}
...
class CameraHomeScreen extends StatefulWidget {
  List<CameraDescription> cameras;
  String initCamera;

  CameraHomeScreen(this.cameras,this.initCamera);
... 
void initState() {
    print( 'widget.initCamera ${widget.initCamera}' );
    if (widget.initCamera == 'back') {
      onCameraSelected(widget.cameras[0]);
    } else {
      onCameraSelected(widget.cameras[1]);
    }

    super.initState();
  }

演示

enter image description here

完整代码

import 'dart:async';
import 'dart:io';

import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

String initCamera;
List<CameraDescription> cameras;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  cameras = await availableCameras();
  SharedPreferences pre = await SharedPreferences.getInstance();
  //await prefs.setString("cameraSelected","front");
  initCamera = await pre.getString("cameraSelected");
  print('initCamera ${initCamera}');
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then,without quitting the app,try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",// or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,),home: CameraHomeScreen(cameras,initCamera),);
  }
}


class CameraHomeScreen extends StatefulWidget {
  List<CameraDescription> cameras;
  String initCamera;

  CameraHomeScreen(this.cameras,this.initCamera);

  @override
  State<StatefulWidget> createState() {
    return _CameraHomeScreenState();
  }
}

class _CameraHomeScreenState extends State<CameraHomeScreen> {
  String imagePath;
  bool _toggleCamera = false;
  String _currentCamera = 'back';
  CameraController controller;

  @override
  void initState() {
    print( 'widget.initCamera ${widget.initCamera}' );
    if (widget.initCamera == 'back') {
      onCameraSelected(widget.cameras[0]);
    } else {
      onCameraSelected(widget.cameras[1]);
    }

    super.initState();
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (widget.cameras.isEmpty) {
      return Container(
        alignment: Alignment.center,padding: EdgeInsets.all(16.0),child: Text(
          'No Camera Found',style: TextStyle(
            fontSize: 16.0,color: Colors.white,);
    }

    if (!controller.value.isInitialized) {
      return Container();
    }

    return AspectRatio(
      aspectRatio: controller.value.aspectRatio,child: Container(
        child: Stack(
          children: <Widget>[
            CameraPreview(controller),Align(
              alignment: Alignment.bottomCenter,child: Container(
                width: double.infinity,height: 120.0,padding: EdgeInsets.all(20.0),color: Color.fromRGBO(00,00,0.7),child: Stack(
                  children: <Widget>[
                    Align(
                      alignment: Alignment.center,child: Material(
                        color: Colors.transparent,child: InkWell(
                          borderRadius: BorderRadius.all(Radius.circular(50.0)),onTap: () {
                            _captureImage();
                          },child: Container(
                            padding: EdgeInsets.all(4.0),child: Image.asset(
                              'assets/images/ic_shutter_1.png',width: 72.0,height: 72.0,Align(
                      alignment: Alignment.centerRight,onTap: () {
                            if (!_toggleCamera) {
                              SharedPreferencesHelper prefs =
                                  SharedPreferencesHelper();
                              prefs.setCameraSelected('front');
                              print("front");
                              onCameraSelected(widget.cameras[1]);
                              setState(() {
                                _toggleCamera = true;
                              });
                            } else {
                              SharedPreferencesHelper prefs =
                                  SharedPreferencesHelper();
                              prefs.setCameraSelected('back');
                              print("back");
                              onCameraSelected(widget.cameras[0]);
                              setState(() {
                                _toggleCamera = false;
                              });
                            }
                          },child: Image.asset(
                              'assets/images/ic_switch_camera_3.png',color: Colors.grey[200],width: 42.0,height: 42.0,],);
  }

  void onCameraSelected(CameraDescription cameraDescription) async {
    if (controller != null) await controller.dispose();
    controller = CameraController(cameraDescription,ResolutionPreset.medium);

    controller.addListener(() {
      if (mounted) setState(() {});
      if (controller.value.hasError) {
        showMessage('Camera Error: ${controller.value.errorDescription}');
      }
    });

    try {
      await controller.initialize();
    } on CameraException catch (e) {
      showException(e);
    }

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

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

  void _captureImage() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
        });
        if (filePath != null) {
          showMessage('Picture saved to $filePath');
          setCameraResult();
        }
      }
    });
  }

  void setCameraResult() {
    Navigator.pop(context,imagePath);
  }

  Future<String> takePicture() async {
    if (!controller.value.isInitialized) {
      showMessage('Error: select a camera first.');
      return null;
    }
    final Directory extDir = await getApplicationDocumentsDirectory();
    final String dirPath = '${extDir.path}/FlutterDevs/Camera/Images';
    await new Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/${timestamp()}.jpg';

    if (controller.value.isTakingPicture) {
      // A capture is already pending,do nothing.
      return null;
    }

    try {
      await controller.takePicture(filePath);
    } on CameraException catch (e) {
      showException(e);
      return null;
    }
    return filePath;
  }

  void showException(CameraException e) {
    logError(e.code,e.description);
    showMessage('Error: ${e.code}\n${e.description}');
  }

  void showMessage(String message) {
    print(message);
  }

  void logError(String code,String message) =>
      print('Error: $code\nMessage: $message');
}

class SharedPreferencesHelper {
  ///
  /// Instantiation of the SharedPreferences library
  ///
  final String _nameKey = "cameraSelected";

  /// ------------------------------------------------------------
  /// Method that returns the user decision on sorting order
  /// ------------------------------------------------------------
  Future<String> getCameraSelected() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    return prefs.getString(_nameKey) ?? 'name';
  }

  /// ----------------------------------------------------------
  /// Method that saves the user decision on sorting order
  /// ----------------------------------------------------------
  Future<bool> setCameraSelected(String value) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();

    return prefs.setString(_nameKey,value);
  }
}
本文链接:https://www.f2er.com/3010629.html

大家都在问