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

Posted

技术标签:

【中文标题】在运行时出现此错误“用于空值的空检查运算符”【英文标题】:Getting This Error on Run Time "Null check operator used on a null value" 【发布时间】:2021-10-10 16:46:47 【问题描述】:

我正在使用 api owlbot 构建一个字典应用程序。我的代码运行罚款没有显示错误。但是在运行时间之后,我收到错误════════小部件捕获的异常══════════════════════════════════ ══════════════ 用于空值的空检查运算符 ══════════════════════════════════════════════════ ══════════════════

void main() 
  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(
        primarySwatch: Colors.blue,
      ),
      home: DictionaryPage(),
    );
  

我的词典页面代码:

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:flutter/material.dart';

class DictionaryPage extends StatefulWidget 
  @override
  _DictionaryPageState createState() => _DictionaryPageState();


class _DictionaryPageState extends State<DictionaryPage> 
  String url = "https://owlbot.info/api/v4/dictionary/";
  String token = "Your Key";

  TextEditingController textEditingController = TextEditingController();

  // Stream for loading the text as soon as it is typed
  late StreamController streamController;
  Stream? _stream;

  Timer? _debounce;

  // search function
  searchText() async 
    if (textEditingController.text.length == 0) 
      streamController.add(null);
      return;
    
    streamController.add("waiting");
    Response response =
        await get(url + textEditingController.text.trim() as Uri,
            // do provide spacing after Token
            headers: "Authorization": "Token " + token);
    streamController.add(json.decode(response.body));
  

  @override
  void initState() 
    super.initState();
    streamController = StreamController();
    _stream = streamController.stream;
  

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.black,
          title: Text(
            "Dictionary nw",
            style: TextStyle(color: Colors.white),
          ),
          centerTitle: true,
          bottom: PreferredSize(
            preferredSize: Size.fromHeight(45),
            child: Row(
              children: [
                Expanded(
                  child: Container(
                    margin: const EdgeInsets.only(left: 12, bottom: 11.0),
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(24.0),
                        color: Colors.white),
                    child: TextFormField(
                      onChanged: (String? text) 
                        if (_debounce!.isActive) _debounce?.cancel();
                        _debounce =
                            Timer(const Duration(milliseconds: 1000), () 
                          searchText();
                        );
                      ,
                      controller: textEditingController,
                      decoration: InputDecoration(
                        hintText: "Search for a word",
                        contentPadding: const EdgeInsets.only(left: 24.0),

                        // removing the input border
                        border: InputBorder.none,
                      ),
                    ),
                  ),
                ),
                IconButton(
                  icon: Icon(
                    Icons.search,
                    color: Colors.white,
                  ),
                  onPressed: () 
                    searchText();
                  ,
                )
              ],
            ),
          ),
        ),
        body: Container(
          margin: EdgeInsets.all(8),
          child: StreamBuilder(
            builder: (BuildContext context, AsyncSnapshot snapshot) 
              if (snapshot.data == null) 
                return Center(
                  child: Text("Enter a search word"),
                );
              
              if (snapshot.data == "waiting") 
                return Center(
                  child: CircularProgressIndicator(),
                );
              

              // output
              return ListView.builder(
                itemCount: snapshot.data["definitions"].length,
                itemBuilder: (BuildContext context, int index) 
                  return ListBody(
                    children: [
                      Container(
                        color: Colors.grey[300],
                        child: ListTile(
                          leading: snapshot.data["definitions"][index]
                                      ["image_url"] ==
                                  null
                              ? null
                              : CircleAvatar(
                                  backgroundImage: NetworkImage(snapshot
                                      .data["definitions"][index]["image_url"]),
                                ),
                          title: Text(textEditingController.text.trim() +
                              "(" +
                              snapshot.data["definitions"][index]["type"] +
                              ")"),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Text(
                            snapshot.data["definitions"][index]["definition"]),
                      )
                    ],
                  );
                ,
              );
            ,
            stream: _stream,
          ),
        ),
      ),
    );
  

根据我的研究,我认为这个错误发生在 ,

   if (_debounce!.isActive) _debounce?.cancel();
                        _debounce =
                            Timer(const Duration(milliseconds: 1000), () 
                          searchText();
                        );
                      ,
                     

这个,我需要根据这个改变,

Use a local variable

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

Use ?. and ??

var len = foo?.length ?? 0; 

【问题讨论】:

【参考方案1】:

您需要检查_debounce 是否已经初始化(即它不为空):

onChanged: (String? text) 
  // Use a local variable, as your snippet hints
  final Timer? debounce = _debounce;

  // Check if it's initialized AND if it's active
  if (debounce != null && debounce.isActive)
    debounce.cancel();

  // Initialize a new timer
  _debounce = Timer(const Duration(milliseconds: 1000), () 
    searchText();
  );
,

【讨论】:

就这么做:debounce?.cancel();。如果您在非活动计时器上调用 cancel(),则不会发生任何事情,因此无需测试它是否处于活动状态:api.dart.dev/stable/2.13.4/dart-async/Timer/cancel.html 在“?.”的情况下运算符,您也可以省略对局部变量的赋值。

以上是关于在运行时出现此错误“用于空值的空检查运算符”的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

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

在 Android 手机上运行应用程序时出现此错误

尝试在 vscode 上通过颤振运行应用程序时出现此错误