Flutter词典应用搜索栏LateInitializationError问题修复请求
问题分析与解决
错误原因
- 未初始化的
_debounce变量:代码用late Timer _debounce;声明了延迟初始化变量,但initState里未给它赋值。第一次在搜索栏输入文本触发onChanged时,访问_debounce.isActive会直接抛出LateInitializationError——变量还未被初始化。 - API字段拼写错误:Owlbot词典API返回的定义数组字段是
definitions(正确复数拼写),但代码里错误写成了defination/definations,会导致搜索成功后渲染数据时出现异常。
修复步骤
1. 修复定时器初始化问题
将late Timer _debounce;改为可空类型,避免强制延迟初始化的限制:
Timer? _debounce;
同时修改onChanged中的判断逻辑,确保安全访问定时器状态:
onChanged: (String text) { // 先判断定时器是否存在且活跃,再取消 if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 1000), () { searchText(); }); },
2. 修正API字段拼写错误
- 将列表长度判断中的
snapshot.data["defination"].length改为:itemCount: snapshot.data["definitions"].length, - 将ListTile中的
snapshot.data["definations"][index]改为:snapshot.data["definitions"][index] - 将定义文本中的
snapshot.data["defination"][index]["defination"]改为:snapshot.data["definitions"][index]["definition"]
3. 优化:添加资源清理(可选)
在dispose方法中关闭流控制器、销毁文本控制器并取消定时器,避免内存泄漏:
@override void dispose() { _streamController.close(); textEditingController.dispose(); _debounce?.cancel(); // 清理定时器 super.dispose(); }
完整修正代码
import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatefulWidget { @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { String url = "https://owlbot.info/api/v4/dictionary/"; String token = "7ba05536bd11ff8e22800cbda80951376c59ed84"; TextEditingController textEditingController = TextEditingController(); late StreamController _streamController; late Stream _stream; Timer? _debounce; // 修改为可空类型 searchText() async { if (textEditingController.text.isEmpty) { _streamController.add(null); return; } _streamController.add("waiting"); Uri uri = Uri.parse(url + textEditingController.text.trim()); http.Response response = await http.get(uri, headers: {"Authorization": "Token " + token}); _streamController.add(json.decode(response.body)); } @override void initState() { super.initState(); _streamController = StreamController(); _stream = _streamController.stream; } @override void dispose() { _streamController.close(); textEditingController.dispose(); _debounce?.cancel(); // 清理定时器 super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.green, title: Text( "Dictionary", // 修正拼写错误 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), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(24), ), child: TextFormField( onChanged: (String text) { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 1000), () { searchText(); }); }, controller: textEditingController, decoration: InputDecoration( hintText: "Search for Word", contentPadding: const EdgeInsets.only(left: 24), border: InputBorder.none, ), ), ), ), IconButton( icon: Icon( Icons.search, color: Colors.white, ), onPressed: () { searchText(); }, ), ], ), ), ), body: Container( margin: EdgeInsets.all(8.0), 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(), ); } 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, ), ), ); } }
内容的提问来源于stack exchange,提问作者Muhammad Danish Khan
相关产品推荐
相关产品推荐

