用于空值的空检查运算符

Posted

技术标签:

【中文标题】用于空值的空检查运算符【英文标题】:Null check operator used on a null value 【发布时间】:2021-01-24 10:47:22 【问题描述】:

我是Flutter的新手

当我运行我的简单颤振应用程序时出现此错误。我不知道为什么会发生这个错误。

错误

Null check operator used on a null value

我在 main.dart 中的代码

import 'package:flutter/material.dart';
import './ui/login.dart';

void main() 
  
  runApp(new MaterialApp(
    title: "Login Template",
    home: new Login(),
  ));


我在 login.dart 中的代码

import 'package:flutter/material.dart';

class Login extends StatefulWidget 
  @override
  State<StatefulWidget> createState() 
    return new LoginState();
  


class LoginState extends State<Login> 
  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Login"),
        centerTitle: true,
        backgroundColor: Colors.blueAccent.shade50,
      ),
      backgroundColor: Colors.blueGrey,
      body: new Container(

      ),
    );
  


代码的错误跟踪

Running Gradle task 'assembleDebug'...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Waiting for SM J710F to report its views...
D/vndksupport(29495): Loading /vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl.so from current namespace instead of sphal namespace.
Debug service listening on ws://127.0.0.1:39899/9RorUiKtUb4=/ws
Syncing files to device SM J710F...
D/ViewRootImpl@4ac1ef4[MainActivity](29495): MSG_RESIZED_REPORT: frame=Rect(0, 0 - 720, 1280) ci=Rect(0, 48 - 0, 582) vi=Rect(0, 48 - 0, 582) or=1
D/ViewRootImpl@4ac1ef4[MainActivity](29495): MSG_WINDOW_FOCUS_CHANGED 1
V/InputMethodManager(29495): Starting input: tba=android.view.inputmethod.EditorInfo@3049fea nm : com.sivaram.login_template ic=null
D/InputMethodManager(29495): startInputInner - Id : 0
I/InputMethodManager(29495): startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport(29495): Input channel constructed: fd=96
V/InputMethodManager(29495): Starting input: tba=android.view.inputmethod.EditorInfo@aad92db nm : com.sivaram.login_template ic=null
D/InputMethodManager(29495): startInputInner - Id : 0
D/ViewRootImpl@4ac1ef4[MainActivity](29495): MSG_RESIZED: frame=Rect(0, 0 - 720, 1280) ci=Rect(0, 48 - 0, 0) vi=Rect(0, 48 - 0, 0) or=1
D/ViewRootImpl@4ac1ef4[MainActivity](29495): Relayout returned: old=[0,0][720,1280] new=[0,0][720,1280] result=0x1 surface=valid=true 3791374336 changed=false
D/libGLESv2(29495): STS_GLApi : DTS, ODTC are not allowed for Package : com.sivaram.login_template

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
Null check operator used on a null value
Login file:///home/kadavul/IdeaProjects/login_template/lib/main.dart:8:15
════════════════════════════════════════════════════════════════════════════════════════════════════
V/InputMethodManager(29495): Starting input: tba=android.view.inputmethod.EditorInfo@a0ff0af nm : com.sivaram.login_template ic=null
D/InputMethodManager(29495): startInputInner - Id : 0
I/InputMethodManager(29495): startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport(29495): Input channel constructed: fd=87
D/InputTransport(29495): Input channel destroyed: fd=96
D/SurfaceView(29495): windowStopped(true) false 77b9092 of ViewRootImpl@4ac1ef4[MainActivity]
D/SurfaceView(29495): BG show() Surface(name=Background for - SurfaceView - com.sivaram.login_template/com.sivaram.login_template.MainActivity@77b9092@0) io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
D/SurfaceView(29495): surfaceDestroyed 1 #1 io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
V/InputMethodManager(29495): Starting input: tba=android.view.inputmethod.EditorInfo@a78fcbc nm : com.sivaram.login_template ic=null
D/InputMethodManager(29495): startInputInner - Id : 0
I/InputMethodManager(29495): startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport(29495): Input channel constructed: fd=91
D/InputTransport(29495): Input channel destroyed: fd=87
D/SurfaceView(29495): windowStopped(false) true 77b9092 of ViewRootImpl@4ac1ef4[MainActivity]
D/SurfaceView(29495): BG show() Surface(name=Background for - SurfaceView - com.sivaram.login_template/com.sivaram.login_template.MainActivity@77b9092@1) io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
V/Surface (29495): sf_framedrop debug : 0x4f4c, game : false, logging : 0
D/SurfaceView(29495): surfaceCreated 1 #1 io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
D/mali_winsys(29495): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, egl_color_buffer_format *, EGLBoolean) returns 0x3000,  [720x1280]-format:1
D/SurfaceView(29495): surfaceChanged (720,1280) 1 #1 io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
D/SurfaceView(29495): BG destroy() Surface(name=Background for - SurfaceView - com.sivaram.login_template/com.sivaram.login_template.MainActivity@77b9092@0) io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
D/ViewRootImpl@4ac1ef4[MainActivity](29495): Relayout returned: old=[0,0][720,1280] new=[0,0][720,1280] result=0x3 surface=valid=true 3791374336 changed=false
D/ViewRootImpl@4ac1ef4[MainActivity](29495): MSG_RESIZED_REPORT: frame=Rect(0, 0 - 720, 1280) ci=Rect(0, 48 - 0, 0) vi=Rect(0, 48 - 0, 0) or=1
V/InputMethodManager(29495): Starting input: tba=android.view.inputmethod.EditorInfo@7ed1445 nm : com.sivaram.login_template ic=null
D/InputMethodManager(29495): startInputInner - Id : 0
I/InputMethodManager(29495): startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport(29495): Input channel constructed: fd=92
D/InputTransport(29495): Input channel destroyed: fd=91
D/SurfaceView(29495): windowStopped(true) false 77b9092 of ViewRootImpl@4ac1ef4[MainActivity]
D/SurfaceView(29495): BG show() Surface(name=Background for - SurfaceView - com.sivaram.login_template/com.sivaram.login_template.MainActivity@77b9092@1) io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280
D/SurfaceView(29495): surfaceDestroyed 1 #1 io.flutter.embedding.android.FlutterSurfaceView77b9092 V.E...... ........ 0,0-720,1280

我的颤振医生输出


fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
Doctor summary (to see all details, run flutter doctor -v):
Failed to find the latest git commit date: VersionCheckError: Command exited with code 128: git -c log.showSignature=false log -n 1 --pretty=format:%ad --date=iso
Standard out: 
Standard error: fatal: your current branch 'master' does not have any commits yet

Returning 1970-01-01 05:30:00.000 instead.
[✓] Flutter (Channel unknown, 0.0.0-unknown, on Linux, locale en_US.UTF-8)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[✓] Android Studio (version 4.0)
[!] VS Code (version 1.50.0)
    ✗ Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)

! Doctor found issues in 1 category.

谁能为此提供解决方案?

【问题讨论】:

在终端执行颤振医生 你能复制粘贴确切的错误跟踪吗?也许我们可以找到问题出在哪里 添加了错误跟踪 你用的是稳定频道还是master? 我认为是大师 【参考方案1】:

不要降级 Flutter

问题:

当您在未初始化的可为空的实例上使用 bang 运算符 (!) 时会发生此错误。

例如:

String? foo; // Nullable String

void main() 
  var len = foo!.length; // Runtime error: Null check operator used on a null value

解决方案:

您需要找出在代码中使用 bang 运算符的位置。到达那里后,您可以使用以下任何一种解决方案:

使用局部变量

var f = foo;
if (f != null) 
  var len = f.length; // Safe 

使用 ?. 和 ??

var len = foo?.length ?? 0; // Provide a default value if foo was null.

回答您的问题:

你正在使用

Colors.blueAccent.shade50

没有50th 阴影。如果你查看源代码,你会发现:

Color get shade50 => this[50]!; // <-- This bang operator is causing the error.

要解决此错误,您应该使用不是null 的其他颜色,可能是100th 阴影。

Colors.blueAccent[100]
// or
Colors.blue.shade100

对于那些正在使用FutureBuilder/StreamBuilder的人:

您可以通过两种方式解决该错误:

为您的FutureBuilder/StreamBuilder指定一个类型

FutureBuilder<List<int>>( // <-- type 'List<int>' is specified.
  future: _listOfInt(),
  builder: (_, snapshot) 
    if (snapshot.hasData) 
      List<int> myList = snapshot.data!; // <-- Your data
    
    return Container();
  ,
)

使用asObject 向下转换为您的类型,例如ListMap

FutureBuilder(
  future: _listOfInt(),
  builder: (_, snapshot) 
    if (snapshot.hasData) 
      var myList = snapshot.data! as List<int>; // <-- Your data using 'as'
    
    return Container();
  ,
)

【讨论】:

【参考方案2】:

任何使用 get_it 包并遇到类似问题的人,这里是最简单的解决方案。 只需在主函数顶部添加 WidgetsFlutterBinding.ensureInitialized(); 即可。

像这样改变你的主要功能:

Future<void> main() async 
WidgetsFlutterBinding.ensureInitialized();
await di.init()
runApp(MyApp());

【讨论】:

path_provider 包相同 非常感谢@AaNeal O'Neal 申请也开始了,我只想知道这意味着什么?请解释一下好吗? 基本上,它返回一个 WidgetsBinding 的实例,并在必要时创建并初始化它。如果创建了一个,它将是一个 WidgetsFlutterBinding。如果之前已经初始化过,那么它至少会实现 WidgetsBinding。只有在调用runApp之前需要初始化绑定时才需要调用该方法。【参考方案3】:

首选CopsOnRoad answer,只有在不起作用时才降级。

解决上述问题需要的步骤如下


 - flutter channel stable 
 - flutter upgrade
 - flutter pub cache repair //To perform a clean reinstall of the packages in your system cache, use pub cache repair
 - flutter clean //flutter clean will delete the /build folder

当我尝试flutter channel stable 时。我遇到了另一个错误,因为我有两个颤振,一个来自 snapd,另一个来自 git clone 方法。

然后,我使用 git clone 配置了 SDK。最后,我使用 Git 克隆的 SDK Flutter 执行如下所有命令

flutter channel stable 
 - ~/flutter/bin/flutter upgrade
 - ~/flutter/bin/flutter pub cache repair //To perform a clean reinstall of the packages in your system cache, use pub cache repair
 - ~/flutter/bin/flutter clean //flutter clean will delete the /build folder

【讨论】:

就我而言,这并没有解决问题,但升级/清理后错误消息更清晰,因此我可以找到“真正的原因”(缺少 cupertino 小部件的本地化)。跨度> 当你需要在测试通道上运行时,有什么办法可以颠覆这个消息?我有类似的问题,但我正在为 MacBook M1 运行测试版,所以不能真正使用稳定通道。 我也无法切换到稳定的频道,因为我的程序依赖于最低 sdk 版本 2.12.0(或者我认为这是我还不完全理解颤振的问题)所以我正在运行开发频道。那么有没有什么办法可以在不切换频道的情况下解决这个问题呢?【参考方案4】:

该问题可能与dartlang 中集成的空安全性有关。现在您可以切换频道并使用稳定频道:

flutter channel stable
flutter upgrade

【讨论】:

在稳定频道上,最新的flutter,firebase插件在这里抛出这个错误` ///用户的唯一ID。字符串获取 uid return _data['uid']!; ` 当监听用户更改并打印最新用户时,它会抛出我Null check operator used on a null value 它会导致 user_info.dart 文件中上述注释的行 谢谢,但是我应该在哪里输入呢? 在终端中【参考方案5】:

对于像我这样的新手,请尝试重新启动应用程序而不是热重新加载它。

【讨论】:

【参考方案6】:

Provider 反模式

如果我们在我们的包之外得到这个错误,那么我们可能需要看看我们是如何使用第三方依赖的。就我而言,Provider 反模式导致了问题。

Provider 对象的生命周期与常规小部件不同,因为它可以是 unexpectedly re-created or not created at all,具体取决于使用情况。

示例 1

create: 块之外初始化ChangeNotifierProvider 时,我遇到了一个简单的可重现示例。

ChangeNotifierProvider(
  create: (_) => ToDoContainerModel(),
  builder: (context, _) 
    return home;
));

不好

ChangeNotifierProvider(
  create: (_) => model,
  builder: (context, _) 
    return home;
));

这在the repository 中被记录为反模式:

不要使用默认构造函数重用现有的 ChangeNotifier。

示例 2

另一个可能导致类似副作用的反模式是:

如果您想创建一个对象,请不要使用.value 构造函数,否则您可能会产生不希望的副作用。

ChangeNotifierProvider.value(
  create: (_) => MyModel(),
  child: ...
)

不好

ChangeNotifierProvider.value(
  value: MyModel(),
  child: ...
)

错误原因

sqflite 数据库应该只调用一次openDatabase 以保持一致性。使用ChangeNotifierProvider 反模式,我得到了这个错误,因为我不止一次触发了openDatabase。因此,我触发了未处理的异常,因为当我们在重复调用中指定相同的数据库路径时,sqflite 在内部为openDatabase 返回 null。

提示:当您在包之外遇到此错误时,请检查第三方文档。

【讨论】:

以上是关于用于空值的空检查运算符的主要内容,如果未能解决你的问题,请参考以下文章

在运行时出现此错误“用于空值的空检查运算符”

Navigator.pushReplacement 提供用于空值的空检查运算符。这次是 - 状态

如何修复颤振中的“未处理的异常:用于空值的空检查运算符”错误?

如何在颤振发布方法中修复“未处理的异常:用于空值的空检查运算符”

颤振错误,对空值使用空检查运算符

用于空值 Flutter 的空值检查运算符