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

Flutter 从API拉取名言列表时SearchDelegate无搜索结果如何解决?

问题根因

  • Search类中定义的接口请求方法getPost从未触发调用,存储名言的quotes数组始终为空,无数据可筛选
  • 筛选逻辑存在类型错误:quotes中存储的是包含text、author字段的Map对象,直接对Map对象调用toLowerCase()无法匹配到搜索词
  • 接口请求冗余:ListPage页面已经完成全量名言数据拉取,Search中重复请求属于不必要的资源浪费
  • 列表渲染逻辑错误:直接将Map对象作为Text组件的内容,会导致渲染异常

修复方案

1. 重构Search类,支持接收外部传入数据、修正筛选与渲染逻辑

import 'package:flutter/material.dart';

class Search extends SearchDelegate<String> {
  final List quotes; // 接收外部传入的已拉取名言数据
  String result = "";

  Search({
    required this.quotes,
  });

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
        icon: const Icon(Icons.clear),
        onPressed: () {
          query = '';
        },
      )
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      icon: const Icon(Icons.arrow_back),
      onPressed: () {
        close(context, result);
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {
    final suggestions = quotes.where((quoteItem) {
      final quoteText = quoteItem["text"]?.toString().toLowerCase() ?? "";
      final quoteAuthor = quoteItem["author"]?.toString().toLowerCase() ?? "";
      final queryLower = query.toLowerCase();
      // 同时匹配名言内容和作者
      return quoteText.contains(queryLower) || quoteAuthor.contains(queryLower);
    }).toList();

    return ListView.builder(
      itemCount: suggestions.length,
      itemBuilder: (BuildContext context, int index) {
        final item = suggestions[index];
        return ListTile(
          title: Text(item["text"] ?? ""),
          subtitle: Text(item["author"] ?? "未知作者", style: const TextStyle(color: Colors.redAccent),),
          onTap: () {
            result = item["text"] ?? "";
            close(context, result);
          },
        );
      },
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    // 建议列表和结果列表共用同一筛选逻辑
    return buildResults(context);
  }
}

2. 修改ListPage代码,缓存已拉取数据并传入Search实例

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// 导入你修改后的Search类
import 'package:flutterquote/model/search.dart';

class ListPage extends StatefulWidget {
  @override
  _ListPageState createState() => _ListPageState();
}

class _ListPageState extends State<ListPage> {
  List _allQuotes = []; // 缓存全量名言数据

  Future<List<dynamic>> getPost() async {
    final response = await http.get(Uri.https('type.fit', 'api/quotes'));
    return postFromJson(response.body);
  }

  List<dynamic> postFromJson(String str) {
    List<dynamic> jsonData = json.decode(str);
    _allQuotes = jsonData.toList(); // 拉取成功后缓存全量数据
    return jsonData;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color(0xff171717),
        appBar: AppBar(
          toolbarHeight: 80,
          title: const Text(''),
          backgroundColor: Colors.transparent,
          elevation: 0,
          actions: <Widget>[
            IconButton(
              icon: const Icon(Icons.search, color: Colors.white,),
              onPressed: () async {
                final result = await showSearch<String>(
                  context: context,
                  // 将缓存的全量数据传入Search实例
                  delegate: Search(quotes: _allQuotes),
                );
                print(result);
              },
            )
          ],
        ),
        body: Container(
          color: const Color(0xff171717),
          child: FutureBuilder(
            future: getPost(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  print(snapshot);
                  return ErrorWidget(snapshot);
                }
                return ListView.separated(
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    var model = snapshot.data![index];
                    return ListTile(
                      leading: const Icon(Icons.format_quote, color: Colors.white,),
                      title: Text(
                        model["text"].toString(),
                        style: const TextStyle(color: Colors.white),
                      ),
                      subtitle: Text(
                        model["author"].toString(),
                        style: const TextStyle(color: Colors.redAccent),
                      ),
                    );
                  },
                  separatorBuilder: (BuildContext context, int index) {
                    return const SizedBox(
                      height: 20,
                    );
                  },
                );
              } else
                return const Center(child: CircularProgressIndicator(color: Colors.white,));
            },
          ),
        ));
  }
}

可选优化

你已经定义了QuoteModel类,可以将接口返回的Map数据统一转换为QuoteModel实例操作,避免直接操作Map出现字段名拼写错误等问题。


内容的提问来源于stack exchange,提问作者Robin Rivera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:27:03