dart - 构建 FutureBuilder<List<dynamic>> 时抛出了 StackOverflowError

标签 dart flutter future

我正在使用纽约时报畅销书 API,以便我可以获得畅销书中每个类别的图书列表。我的代码是这样的:

import "dart:convert";
import "package:flutter/material.dart";
import "package:http/http.dart" as http;
import "package:best_sellers/api.dart";

class BestSellersList extends StatefulWidget {
  final API api;
  final List<dynamic> categories;

  BestSellersList({Key key, @required this.api, @required this.categories}) : super(key: key);

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

class _BestSellersList extends State<BestSellersList> {
  String base, key;
  List<dynamic> categories;
  Future<List<dynamic>> books;

  Future<List<dynamic>> fetchBooks() async {
    try {
      final books = categories.map((category) async {
        final listNameEncoded = category["list_name_encoded"];
        final uri = "$base/$listNameEncoded?api-key=$key";
        final response = await http.get(uri);
        if (response.statusCode == 200) {
          final responseBody = json.decode(response.body);
          final books = responseBody["results"]["books"];
          return books;
        } else { throw Exception(); }
      }).toList();

      if (books.isNotEmpty) {
        return books;
      }
      throw Exception();
    } catch(e) { /**/ }
  }

  void updateBooks() {
    setState(() {
      books = updateBooks();
    });
  }

  @override
  initState() {
    super.initState();
    base = widget.api.base;
    key = widget.api.key;
    categories = widget.categories;
    print("categories.length: ${categories.length}"); // categories.length: 55
    updateBooks();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: books,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (context, index) {
              final displayName = snapshot.data[index]["display_name"];
              return ListTile(title: Text(displayName));
            }
          );
        } else if (snapshot.hasError) {
          return Center(child: Column(
            children: [
              Text(snapshot.error.toString()),
              RaisedButton(
                onPressed: () => updateBooks(),
                child: Text("RETRY"),
              ),
            ],
          ));
        }

        return Center(child: CircularProgressIndicator());
      }
    );
  }
}

在运行我的代码时,我得到了这个堆栈跟踪:

    I/flutter ( 5231): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
I/flutter ( 5231): The following StackOverflowError was thrown building FutureBuilder<List<dynamic>>(state:
I/flutter ( 5231): _FutureBuilderState<List<dynamic>>#a3252):
I/flutter ( 5231): Stack Overflow
I/flutter ( 5231): When the exception was thrown, this was the stack:
I/flutter ( 5231): #0      State.mounted (package:flutter/src/widgets/framework.dart:969:3)
I/flutter ( 5231): #1      State.setState.<anonymous closure>
(package:flutter/src/widgets/framework.dart:1113:63)
I/flutter ( 5231): #2      State.setState (package:flutter/src/widgets/framework.dart:1123:6)
I/flutter ( 5231): #3      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #4      _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #5      State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #6      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #7      _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #8      State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #9      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #10     _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #11     State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #12     _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #13     _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
                ...................................................
                ...................................................
                ...................................................
    I/flutter ( 5231): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
I/flutter ( 5231): The following StackOverflowError was thrown building FutureBuilder<List<dynamic>>(state:
I/flutter ( 5231): _FutureBuilderState<List<dynamic>>#a3252):
I/flutter ( 5231): Stack Overflow
I/flutter ( 5231): When the exception was thrown, this was the stack:
I/flutter ( 5231): #0      State.mounted (package:flutter/src/widgets/framework.dart:969:3)
I/flutter ( 5231): #1      State.setState.<anonymous closure>
(package:flutter/src/widgets/framework.dart:1113:63)
I/flutter ( 5231): #2      State.setState (package:flutter/src/widgets/framework.dart:1123:6)
I/flutter ( 5231): #3      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #4      _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #5      State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #6      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #7      _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #8      State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #9      _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #10     _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)
I/flutter ( 5231): #11     State.setState (package:flutter/src/widgets/framework.dart:1124:30)
I/flutter ( 5231): #12     _BestSellersList.updateBooks (package:best_sellers/best_sellers_list.dart:44:9)
I/flutter ( 5231): #13     _BestSellersList.updateBooks.<anonymous closure>
(package:best_sellers/best_sellers_list.dart:45:19)

据我所知,该错误位于 fetchBooks() 方法中,该方法又由 updateBooks() 方法调用,并且 StackoverflowError 是由过深或无限递归引起的。我正在迭代的 categories 列表有 55 个项目。

最佳答案

这是循环:

  void updateBooks() {       // called from vvv
    setState(() {
      books = updateBooks(); // <<<< calls ^^^
    });
  }

你可能想要这样的东西

  void updateBooks() async {     
    var result = await fetchBooks();
    setState(() {
      books = result;
    });
  }

关于dart - 构建 FutureBuilder<List<dynamic>> 时抛出了 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53285136/

相关文章:

android - 元素类型 '{0}'无法分配给列表类型 '{1}' flutter

flutter - 如何在 Dart 中返回 Future<T> 结果

scala - Play 2.5.x (Scala) -- 如何将通过 wsClient 获得的值放入(惰性)val

Flutter MQTT 客户端分离套接字无法同时实现 'Stream<List<int>>' 和 'Stream<Uint8List>'

android - Flutter Blue无法检测到蓝牙打印机(Zebra ez320)

dart - 使用 MaterialApp 路由在屏幕旋转时调用 Widget 的 didUpdateWidget 方法

asynchronous - 在Flutter中将Future <int>转换为int

clojure - Clojure future 和 Promise 有何不同?

dart - 如何检查 dart 中的特定位?

flutter - 类型 List<dynamic> 不是类型 'Map<String, dynamic>' 的子类型