Flutter:类型“(dynamic) => dynamic”不是 'test' 类型“(Book) => bool”的子类型

Flutter : type '(dynamic) => dynamic' is not a subtype of type '(Book) => bool' of 'test'

我想在我的内容中进行搜索,但我的代码遇到了问题。当我单击我的搜索图标时,它首先显示没有数据,然后显示错误(抛出另一个异常:type '(dynamic) => dynamic' is not a subtype of type '(Book) => bool' of 'test').

我像这样在主屏幕的 AppBar 上创建了一个搜索图标 -

actions: <Widget>[
            FutureBuilder(
                future: fetchBooks(http.Client()),
                builder: (context, snapshot) {
                  return IconButton(
                    icon: Icon(Icons.search),
                    onPressed: () {
                      showSearch(
                          context: context,
                          delegate: BooksSearch(snapshot.data));
                    },
                  );
                }),
          ],

Here is my model.dart -

import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;

Future<List<Book>> fetchBooks(http.Client client) async {
  final response =
      await client.get('https://boimarket.abirahsan.com/public/api/v1/books');

  // Use the compute function to run parsePhotos in a separate isolate.
  return compute(parseBooks, response.body);
}

// A function that converts a response body into a List<Photo>.
List<Book> parseBooks(String responseBody) {
  final parsed = jsonDecode(responseBody).cast<String, dynamic>();
  return parsed['data'].map<Book>((json) => Book.fromJson(json)).toList();
}

class Book {
  final String name;
  final String author;
  final String html;
  final String description;
  final int category;

  Book({
    this.name,
    this.author,
    this.description,
    this.html,
    this.category,
  });

  factory Book.fromJson(Map<String, dynamic> json) {
    return Book(
      name: json['name'] as String,
      html: json['html'] as String,
      description: json['description'] as String,
      author: json['author'] as String,
      category: json['category'] as int,
    );
  }
}

and here is my booksearch.dart -

import 'package:flutter/material.dart';
import 'package:boimarket/model/model.dart';
import 'package:http/http.dart' as http;

class BooksSearch extends SearchDelegate<Book> {
  BooksSearch(this.allBooksData);

  final allBooksData;

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

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

  @override
  Widget buildResults(BuildContext context) {
    return Container();
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return FutureBuilder(
        future: fetchBooks(http.Client()),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Center(
              child: Text('No Data'),
            );
          } else {
            final result = allBooksData
                .where((a) => a.name.toLowerCase().contains(query))
                .toList();
            return ListView(
              children: result.map<Widget>((a) => Text(a.name)),
            );
          }
        });
  }
}

我的代码哪里出了问题? 我该如何解决这个错误?

您可以复制粘贴 运行 下面的完整代码
第 1 步:您需要 json['name'].toString() for Unicode
第 2 步:指定数据类型为 List

final List<Book> allBooksData;
...
AsyncSnapshot<List<Book>> snapshot)
...
final List<Book> result

工作演示

完整代码

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'dart:convert' show utf8;

Future<List<Book>> fetchBooks(http.Client client) async {
  final response =
      await client.get('https://boimarket.abirahsan.com/public/api/v1/books');

  // Use the compute function to run parsePhotos in a separate isolate.
  return compute(parseBooks, response.body);
}

// A function that converts a response body into a List<Photo>.
List<Book> parseBooks(String responseBody) {
  final parsed = jsonDecode(responseBody).cast<String, dynamic>();
  return parsed['data'].map<Book>((json) => Book.fromJson(json)).toList();
}

class Book {
  final String name;
  final String author;
  final String html;
  final String description;
  final int category;

  Book({
    this.name,
    this.author,
    this.description,
    this.html,
    this.category,
  });

  factory Book.fromJson(Map<String, dynamic> json) {
    print(json['name'].toString());
    return Book(
      name: json['name'].toString() as String,
      html: json['html'] as String,
      description: json['description'] as String,
      author: json['author'] as String,
      category: json['category'] as int,
    );
  }
}

class BooksSearch extends SearchDelegate<Book> {
  BooksSearch(this.allBooksData);

  final List<Book> allBooksData;

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

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

  @override
  Widget buildResults(BuildContext context) {
    return Container();
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return FutureBuilder(
        future: fetchBooks(http.Client()),
        builder: (context, AsyncSnapshot<List<Book>> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return Text('none');
            case ConnectionState.waiting:
              return Center(
                child: Text('No Data'),
              );
            case ConnectionState.active:
              return Text('');
            case ConnectionState.done:
              if (!snapshot.hasData) {
                return Center(
                  child: Text('No Data'),
                );
              } else {
                print("query $query");
                List<Book> result = allBooksData
                    .where((a) => a.name.toLowerCase().contains(query.toLowerCase()))
                    .toList();
                print("result.length ${result.length}");
                if (result.length != 0) {
                  return ListView.builder(
                    itemCount: result.length,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text('${result[index].name}'),
                      );
                    },
                  );
                } else {
                  return Text("search no data");
                }
              }
          }
        });
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          FutureBuilder(
              future: fetchBooks(http.Client()),
              builder: (context, AsyncSnapshot<List<Book>> snapshot) {
                return IconButton(
                  icon: Icon(Icons.search),
                  onPressed: () {
                    showSearch(
                        context: context, delegate: BooksSearch(snapshot.data));
                  },
                );
              }),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}