断言失败:第 378 行第 10 行:'data != null':必须向文本小部件提供非空字符串

Failed assertion: line 378 pos 10: 'data != null': A non-null String must be provided to a Text widget

我的 flutter 项目开始出现如下错误。你能帮帮我吗?

我的代码:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_clipboard_manager/flutter_clipboard_manager.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'URL Shortener',
      theme: ThemeData(
        primarySwatch: Colors.purple,
      ),
      home: StartPage(),
    );
  }
}

class StartPage extends StatefulWidget {
  @override
  _StartPageState createState() => _StartPageState();
}
class _StartPageState extends State<StartPage> {

  final GlobalKey<ScaffoldState> _globalKey = GlobalKey<ScaffoldState>();
  String shortUrl = "";
  TextEditingController urlcontroller = TextEditingController();
  getData() async {
    var url = 'https://api.shrtco.de/v2/shorten?url=${urlcontroller.text}';
    var response = await http.get(url);
    var result = jsonDecode(response.body);
    setState(() {
      shortUrl = result['result']['short_url'];
    });
  }

  copy(String url) {
    FlutterClipboardManager.copyToClipBoard(url).then((value) {

      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text('Shorted Url Copied!'),
        duration: Duration(seconds: 1),));
    });
  }

  buildRow(String title, String data, bool original) {
    return SingleChildScrollView(
      child: original
          ? Container(
              alignment: Alignment.center,
              child: Text(
                data,
              ))
          : Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Text(
                  title,
                ),
                Text(
                  data,
                ),
                InkWell(
                    onTap: () => copy(shortUrl),
                    child: Icon(Icons.content_copy))
              ],
            ),
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[300],
      body: ListView(
        children: [
          SvgPicture.asset(
            'assets/logo.svg',
          ),
          SvgPicture.asset(
            'assets/illustration.svg',
          ),
          Center(
            child: Text(
              "Let's get started!",
              style: TextStyle(
                  fontSize: 20,
                  color: Color.fromRGBO(53, 50, 62, 10),
                  fontWeight: FontWeight.bold),
            ),
          ),
          Center(
            child: SizedBox(
              width: 200,
              height: 60,
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                    "Paste your first link into the field to shorten it",
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        fontSize: 15,
                        color: Color.fromRGBO(76, 74, 85, 10),
                        fontWeight: FontWeight.bold)),
              ),
            ),
          ),
          SizedBox(
            height: 130,
            child: Stack(
              alignment: Alignment.center,
              children: [
                Container(
                  alignment: Alignment.centerRight,
                  color: Color.fromRGBO(59, 48, 84, 1),
                  child: SvgPicture.asset(
                    'assets/shape.svg',
                    color: Color.fromRGBO(75, 63, 107, 1),
                  ),
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    SizedBox(
                      width: 300,
                      height: 40,
                      child: TextField(
                        controller: urlcontroller,
                        textAlign: TextAlign.center,
                        decoration: InputDecoration(
                            contentPadding: EdgeInsets.all(10.0),
                            border: OutlineInputBorder(
                              borderRadius: const BorderRadius.all(
                                const Radius.circular(10.0),
                              ),
                              borderSide: BorderSide(
                                width: 0,
                                style: BorderStyle.none,
                              ),
                            ),
                            fillColor: Colors.white,
                            filled: true,
                            hintText: 'Shorten a link here ...'),
                      ),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    SizedBox(
                      width: 300,
                      child: ElevatedButton(
                        onPressed: getData,
                        style: ElevatedButton.styleFrom(
                          primary: Colors.blue,
                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(10.0)),
                          minimumSize: Size(60, 40),
                        ),
                        child: Text('SHORTEN IT!'),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
          SizedBox(
                height: 20,
              ),
              Container(
                width: double.infinity,
                child: Column(
                  children: [
                    SizedBox(
                      height: 20,
                    ),
                    buildRow("Shorted Url", shortUrl, false),
                  ],
                ),
              )
        ],
      ),
      
    );
  }
}

调试控制台:

已调度 KeyUpEvent,但状态显示在不同的逻辑键上按下了物理键。如果在实际应用中出现这种情况,请将此错误报告给 Flutter。如果在单元测试中出现这种情况,请确保模拟事件遵循 HardwareKeyboard 中记录的 Flutter 事件模型。这是事件:KeyUpEvent#f92a0(physicalKey: PhysicalKeyboardKey#70053(usbHidUsage: "0x00070053", debugName: "Num Lock"), logicalKey: LogicalKeyboardKey#00103(keyId: "0x200000103", keyLabel: "Shift Right", debugName: "Shift Right"), character: null, timeStamp: 20:32:38.369878, synthesized) 和记录的逻辑键LogicalKeyboardKey#00068(keyId: "0x00000068", keyLabel: "H", debugName: "Key H") 'package:flutter/src/services/hardware_keyboard.dart': 断言失败:第 444 行第 16 行:'_pressedKeys[event.physicalKey] == event.logicalKey'

图片:

此代码最有可能导致问题:

 setState(() {
      shortUrl = result['result']['short_url'];
    });

您正在执行此操作并假设总会有一个 ['result']['short_url']。但这并不安全。此结果仅在 API 成功时发生。我尝试发送格式错误的 url 结果是:

{
    "ok": false,
    "error_code": 2,
    "error": "This is not a valid URL, for more infos see shrtco.de/docs"
}

将它与成功的这个进行比较:

{
    "ok": true,
    "result": {
        "code": "NaiCa",
        "short_link": "shrtco.de/NaiCa",
        "full_short_link": "https://shrtco.de/NaiCa",
        "short_link2": "9qr.de/NaiCa",
        "full_short_link2": "https://9qr.de/NaiCa",
        "short_link3": "shiny.link/NaiCa",
        "full_short_link3": "https://shiny.link/NaiCa",
        "share_link": "shrtco.de/share/NaiCa",
        "full_share_link": "https://shrtco.de/share/NaiCa",
        "original_link": "https://firebase.google.com/docs/functions/http-events"
    }
}

因此,在您的代码中,您需要首先检查 ok 是否为 true,然后根据此使用您的 setState。

您的代码应如下所示:

var result = jsonDecode(response.body);
if(result['ok']){
    setState(() {
      shortUrl = result['result']['short_link'];
    });
 } else {
 print(response);
}

还有一点很重要,在响应中,没有short_url键,他们用的是short_link,这个错字也会导致错误,结果永远是null,尽管 API 返回成功。