Flutter姓名搜索功能失效问题排查与解决求助
Flutter姓名搜索功能失效问题排查求助
在Flutter项目中实现姓名搜索功能时,输入用户姓名后无法按预期过滤并显示结果。已编写_runFilter方法及相关代码,但搜索功能仍无法正常工作,代码如下:
List<Data> data = []; List<Data> allData = []; List<Data> _foundData = []; @override initState() { _foundData = allData; super.initState(); } @override void dispose() { _foundData.clear(); super.dispose(); } void _runFilter(String enteredKeyword) { List<Data> results = []; if (enteredKeyword.isEmpty) { results = allData; } else { results = allData .where( (user) => user.name!.toLowerCase().contains( enteredKeyword.toLowerCase(), ), ) .toList(); } setState(() { _foundData = results; }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: backgroundColor, appBar: const PreferredSize( preferredSize: Size.fromHeight(kToolbarHeight), child: CustomAppbar( title: 'Dosen', ), ), body: Center( child: Padding( padding: const EdgeInsets.only( left: 16, top: 16, right: 16, ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(bottom: 8), child: TextField( onChanged: (value) => _runFilter(value), decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: BorderSide( width: 1, color: Colors.grey.shade300, ), borderRadius: BorderRadius.circular(10), ), focusedBorder: OutlineInputBorder( borderSide: const BorderSide( width: 1, color: Color.fromARGB(255, 255, 255, 255), ), borderRadius: BorderRadius.circular(10), ), hintText: 'Cari nama dosen...', fillColor: const Color.fromARGB(255, 255, 255, 255), filled: true, hintStyle: TextStyle( color: greyColor, ), suffixIcon: Icon( Icons.search, color: greyColor, ), ), ), ), FutureBuilder<List<Data>>( future: ListDosenProvider.getDosen(), builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.connectionState == ConnectionState.done) { return Expanded( child: ListView.builder( physics: const BouncingScrollPhysics(), itemCount: snapshot.data!.length, // itemCount: allData.length, // itemCount: _foundData.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(top: 14), child: Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all( Radius.circular(8), ), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset( 1, 2, ), ), ], ), child: Padding( padding: const EdgeInsets.all(14), child: Row( children: [ Image.asset( 'assets/images/user.png', width: 50, ), const SizedBox( width: 10, ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( snapshot.data![index].name .toString(), style: bold6, ), Text( snapshot.data![index].prodi .toString(), style: regular6, ), const SizedBox( width: 8, ), const SizedBox( height: 5, ), SizedBox( height: 30, width: 90, child: ElevatedButton.icon( onPressed: () { Navigator.of(context).pop(); // ignore: deprecated_member_use launch( 'mailto:${snapshot.data![index].email.toString()}', ); }, icon: Icon( Icons.mail, size: 17, color: primaryColor, ), label: Text('Email', style: bold6.copyWith( color: primaryColor, )), style: ElevatedButton.styleFrom( backgroundColor: const Color( 0xffC5D5FF, ), ), ), ), ], ), ], ), ), ), ); }, ), ); } } else if (snapshot.hasError) { return Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.center, children: [ Center( child: Image.asset( 'assets/images/server.png', height: 100, ), ), const SizedBox( height: 20, ), Text( 'Upsss... Server error!', style: regular4, ) ], ), ); } return Expanded( child: Center( child: CircularProgressIndicator(color: primaryColor), ), ); }, ), ], ), ), ), ); }
已尝试多种方法但搜索功能仍无法正常工作,请求协助解决。
问题排查及修复方案
核心问题点:
- 数据源未关联:
allData始终为空列表,FutureBuilder获取到数据后未将结果赋值给allData,导致_runFilter过滤时没有数据可处理。 - 列表未使用过滤后的数据:当前
ListView.builder的itemCount和itemBuilder都直接使用snapshot.data,完全没有用到过滤后的_foundData,所以输入关键词后界面无变化。 initState调用顺序错误:应先调用super.initState()再初始化变量,当前顺序不符合Flutter生命周期规范。- 冗余的
dispose操作:_foundData.clear()在组件销毁时无必要,列表会随组件回收自动释放。
修复后的关键代码:
List<Data> allData = []; List<Data> _foundData = []; @override void initState() { super.initState(); } void _runFilter(String enteredKeyword) { List<Data> results = []; if (enteredKeyword.isEmpty) { results = List.from(allData); } else { results = allData .where((user) => user.name!.toLowerCase().contains(enteredKeyword.toLowerCase())) .toList(); } setState(() { _foundData = results; }); } // 修复FutureBuilder部分 FutureBuilder<List<Data>>( future: ListDosenProvider.getDosen(), builder: (context, snapshot) { if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) { // 首次获取数据时初始化allData和_foundData if (allData.isEmpty) { allData = snapshot.data!; _foundData = List.from(allData); } return Expanded( child: ListView.builder( physics: const BouncingScrollPhysics(), itemCount: _foundData.length, itemBuilder: (context, index) { final item = _foundData[index]; return Padding( padding: const EdgeInsets.only(top: 14), child: Container( width: MediaQuery.of(context).size.width, decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.all(Radius.circular(8)), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.2), spreadRadius: 1, blurRadius: 9, offset: const Offset(1, 2), ), ], ), child: Padding( padding: const EdgeInsets.all(14), child: Row( children: [ Image.asset('assets/images/user.png', width: 50), const SizedBox(width: 10), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.name.toString(), style: bold6), Text(item.prodi.toString(), style: regular6), const SizedBox(height: 5), SizedBox( height: 30, width: 90, child: ElevatedButton.icon( onPressed: () { Navigator.of(context).pop(); launch('mailto:${item.email.toString()}'); }, icon: Icon( Icons.mail, size: 17, color: primaryColor, ), label: Text('Email', style: bold6.copyWith( color: primaryColor, )), style: ElevatedButton.styleFrom( backgroundColor: const Color(0xffC5D5FF), ), ), ), ], ), ], ), ), ), ); }, ), ); } else if (snapshot.hasError) { return Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: Image.asset( 'assets/images/server.png', height: 100, ), ), const SizedBox(height: 20), Text( 'Upsss... Server error!', style: regular4, ) ], ), ); } return Expanded( child: Center(child: CircularProgressIndicator(color: primaryColor)), ); }, )
内容的提问来源于stack exchange,提问作者Meikisihka
相关产品推荐
相关产品推荐

