Flutter项目报错:TypeError 'Null'不是'(Quote)=>dynamic'的子类型
Flutter 删除语录按钮 TypeError 问题解决
问题场景
开发展示文本并通过按钮删除文本的Flutter应用,运行时抛出错误:
Exception has occured
_TypeError (type 'Null' is not a subtype of type '(Quote) => dynamic')
涉及三个Dart文件:main.dart、QuoteCard.dart、quote.dart。
错误原因
main.dart中回调传递方式错误:
在quotes.map创建QuoteCard时,onRemoveData: delete(quote)是直接执行delete函数,而非传递函数引用。delete执行后返回void(即Null),但onRemoveData需要接收Function(Quote)类型的回调,类型不匹配导致报错。QuoteCard.dart中按钮点击事件绑定错误:
TextButton的onPressed属性需要无参函数(VoidCallback),但onRemoveData(quote)是直接执行回调函数,返回Null,不符合类型要求。
修正方案
1. 修改main.dart
将QuoteCard的onRemoveData参数改为传递函数引用:
// 原错误代码 children: quotes.map((quote) => QuoteCard( quote: quote, onRemoveData: delete(quote), )).toList(), // 修改后代码 children: quotes.map((quote) => QuoteCard( quote: quote, onRemoveData: delete, )).toList(),
2. 修改QuoteCard.dart
将TextButton的onPressed改为匿名函数,确保点击时才执行回调:
// 原错误代码 TextButton.icon( onPressed: onRemoveData(quote), label: Text('delete quote'), icon: Icon(Icons.delete), ) // 修改后代码 TextButton.icon( onPressed: () => onRemoveData(quote), label: Text('delete quote'), icon: Icon(Icons.delete), )
修正后的完整代码
main.dart
// ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors_in_immutables, use_key_in_widget_constructors import 'package:flutter/material.dart'; import 'quote.dart'; import 'QuoteCard.dart'; void main() => runApp(MaterialApp( home: QuoteList() )); class QuoteList extends StatefulWidget { const QuoteList({super.key}); @override State<QuoteList> createState() => QuoteListState(); } class QuoteListState extends State<QuoteList> { List<Quote> quotes = [ Quote(text: 'hello', author: 'Pete'), Quote(text: 'hi', author: 'Bill'), Quote(text: 'hey', author: 'Tom') ]; void delete(Quote quote) { setState(() { quotes.remove(quote); }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: Text('quotes'), centerTitle: true, backgroundColor: Colors.redAccent, ), body: Column( children: quotes.map((quote) => QuoteCard( quote: quote, onRemoveData: delete, )).toList(), ) ); } }
QuoteCard.dart
import 'package:flutter/material.dart'; import 'quote.dart'; class QuoteCard extends StatelessWidget { final Quote quote; final Function(Quote) onRemoveData; QuoteCard({required this.quote, required this.onRemoveData}); @override Widget build(BuildContext context) { return Card( margin: EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0.0), child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Text( quote.text, style: TextStyle( fontSize: 18.0, color: Colors.grey[800] ), ), SizedBox(height: 6.0,), Text( quote.author, style: TextStyle( fontSize: 10.0, color: Colors.grey[700] ), ), SizedBox(height: 8.0,), TextButton.icon( onPressed: () => onRemoveData(quote), label: Text('delete quote'), icon: Icon(Icons.delete), ) ], ), ), ); } }
quote.dart(无需修改)
class Quote { String text; String author; Quote({required this.text, required this.author}); }
补充说明
- 传递回调时要区分函数引用和函数执行:直接写函数名是传递引用(如
delete),加括号传参是立即执行函数(如delete(quote)),后者会返回执行结果而非传递函数本身。 - 按钮
onPressed必须是无参函数,因此需要用匿名函数() => ...包装带参回调,确保仅在点击时执行。
内容的提问来源于stack exchange,提问作者Siddharth Chopra
相关产品推荐
相关产品推荐

