断言失败:第 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 返回成功。
我的 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 返回成功。