You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

已尝试多种方法但搜索功能仍无法正常工作,请求协助解决。


问题排查及修复方案

核心问题点:

  1. 数据源未关联:allData始终为空列表,FutureBuilder获取到数据后未将结果赋值给allData,导致_runFilter过滤时没有数据可处理。
  2. 列表未使用过滤后的数据:当前ListView.builder的itemCount和itemBuilder都直接使用snapshot.data,完全没有用到过滤后的_foundData,所以输入关键词后界面无变化。
  3. initState调用顺序错误:应先调用super.initState()再初始化变量,当前顺序不符合Flutter生命周期规范。
  4. 冗余的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:47:47