颤动如何在初始化状态下使用未来的异步方法

Posted

技术标签:

【中文标题】颤动如何在初始化状态下使用未来的异步方法【英文标题】:flutter how to use future async method in init state 【发布时间】:2020-10-19 16:42:31 【问题描述】:

当屏幕加载时,我希望初始化状态用通过有状态小部件传递的 Future 填充列表。但是,由于它是一个未来,我的方法会崩溃并且不起作用。

我的代码

  @override
  void initState() async 
    FutureBuilder(
      future: widget.imageList,
      builder: (context, snapshot) 
        switch (snapshot.connectionState) 
          case ConnectionState.none:
            print('NONE');
            break;
          case ConnectionState.active:
          case ConnectionState.waiting:
            print("WAITING");
            break;
          case ConnectionState.done:
            print("DONE");
            setState(() 
              imgList = widget.imageList as List<String>;
            );
            break;
        
      ,
    );
    super.initState();
  

产生错误


════════ Exception caught by widgets library ═══════════════════════════════════
_BottomSheetWidgetState.initState() returned a Future.
The relevant error-causing widget was
    MaterialApp 

列表通过的有状态小部件

List<String> imgList = List<String>();

class BottomSheetWidget extends StatefulWidget 
  BottomSheetWidget(Key key, this.name, this.imageList) : super(key: key);

  String name;
  Future<List<String>> imageList;

整个编辑的代码:

List<String> imgList = List<String>();

class BottomSheetWidget extends StatefulWidget 
  BottomSheetWidget(Key key, this.name, this.imageList) : super(key: key);

  String name;
  Future<List<String>> imageList;

  @override
  _BottomSheetWidgetState createState() => _BottomSheetWidgetState();


class _BottomSheetWidgetState extends State<BottomSheetWidget> 
  int _current = 0;

  final List<Widget> imageSliders = imgList
      .map((item) => Container(
            child: Container(
              margin: EdgeInsets.all(5.0),
              child: ClipRRect(
                  borderRadius: BorderRadius.all(Radius.circular(5.0)),
                  child: Stack(
                    children: <Widget>[
                      Image.network(item,
                          fit: BoxFit.cover, height: 1000.0, width: 1000.0),
                      Positioned(
                        bottom: 0.0,
                        left: 0.0,
                        right: 0.0,
                        child: Container(
                          decoration: BoxDecoration(
                            gradient: LinearGradient(
                              colors: [
                                Color.fromARGB(200, 0, 0, 0),
                                Color.fromARGB(0, 0, 0, 0)
                              ],
                              begin: Alignment.bottomCenter,
                              end: Alignment.topCenter,
                            ),
                          ),
                        ),
                      ),
                    ],
                  )),
            ),
          ))
      .toList();

  @override
  Widget build(BuildContext context) 
    return FutureBuilder(
      future: widget.imageList,
      builder: (context, snapshot) 
        switch (snapshot.connectionState) 
          case ConnectionState.none:
            print('NONE');
            break;
          case ConnectionState.active:
          case ConnectionState.waiting:
            print("WAITING");
            break;
          case ConnectionState.done:
            print("DONNE");
            setState(() async 
                imgList = snapshot.data as List<String>;

            );

            return Container(
              decoration: BoxDecoration(
                color: Colors.red,
                borderRadius: BorderRadius.circular(25),
              ),
              height: MediaQuery.of(context).size.height * 0.85,
              width: MediaQuery.of(context).size.width,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.symmetric(horizontal: 15),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: <Widget>[
                        CarouselSlider(
                          items: imageSliders,
                          options: CarouselOptions(
                              enlargeCenterPage: true,
                              enlargeStrategy: CenterPageEnlargeStrategy.height,
                              height: MediaQuery.of(context).size.height - 500,
                              aspectRatio: 2.0,
                              onPageChanged: (index, reason) 
                                setState(() 
                                  _current = index;
                                );
                              ),
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: imgList.map((url) 
                            int index = imgList.indexOf(url);
                            return Container(
                              width: 8.0,
                              height: 8.0,
                              margin: EdgeInsets.symmetric(
                                  vertical: 10.0, horizontal: 2.0),
                              decoration: BoxDecoration(
                                shape: BoxShape.circle,
                                color: _current == index
                                    ? Color.fromRGBO(0, 0, 0, 0.9)
                                    : Color.fromRGBO(0, 0, 0, 0.4),
                              ),
                            );
                          ).toList(),
                        ),
                        Text(widget.name,
                            style: TextStyle(
                                fontSize: 30,
                                color: Colors.white,
                                fontWeight: FontWeight.bold)),
                        Text("United Kingdom",
                            style: TextStyle(
                              fontSize: 18,
                              color: Colors.white,
                            )),
                      ],
                    ),
                  )
                ],
              ),
            );
            break;
        
      ,
    );
  

来自控制台的新错误:

flutter: WAITING

════════ Exception caught by widgets library ═══════════════════════════════════
A build function returned null.
The relevant error-causing widget was
    FutureBuilder<List<String>> 
lib/common_widget/bottom_sheet.dart:54
════════════════════════════════════════════════════════════════════════════════
flutter: DONNE

════════ Exception caught by widgets library ═══════════════════════════════════
setState() callback argument returned a Future.
The relevant error-causing widget was
    FutureBuilder<List<String>> 
lib/common_widget/bottom_sheet.dart:54
════════════════════════════════════════════════════════════════════════════════

【问题讨论】:

这应该在 build 方法中完成,而不是在 initt 中 我还在学习flutter,被归类为初学者。我把它放在初始化状态的唯一原因是因为我希望它在其他任何事情之前先运行。那么如果我将它包含在构建中,它仍然会首先运行吗? FutureBuilder 小部件为您提供snapshot,其中包含有关未来是否已完成的详细信息。在渲染依赖于未来结果的其他小部件之前,您可以使用它来检查未来是否已经完成。从FutureBuilderbuilder 回调函数返回的任何小部件都将在创建FutureBuilder 之后创建。 【参考方案1】:

initState 方法在设计上是同步的。您可以在覆盖的build 方法中返回FutureBuilder 小部件,而不是在initState 方法中创建FutureBuilder 小部件。请随意查看FutureBuilder 小部件here 的文档,了解其工作原理。

setState 回调函数中的代码似乎也存在问题。您可能希望将 imgList = widget.imageList as List&lt;String&gt;; 替换为 imgList = snapshot.data as List&lt;String&gt;;,以便使用已完成未来的数据。

看起来build 方法在所有情况下都没有返回小部件也存在问题。我已经获取了您更新的代码示例并对其进行了如下修改:

import 'package:flutter/material.dart';

class BottomSheetWidget extends StatefulWidget 
  BottomSheetWidget(Key key, this.name, this.imageList) : super(key: key);

  final String name;

  final Future<List<String>> imageList;

  @override
  _BottomSheetWidgetState createState() => _BottomSheetWidgetState();


class _BottomSheetWidgetState extends State<BottomSheetWidget> 
  int _current = 0;

  @override
  Widget build(BuildContext context) 
    return FutureBuilder<List<String>>(
      future: widget.imageList,
      builder: (context, snapshot) 
        if (snapshot.connectionState == ConnectionState.done) 
          final imgList = snapshot.data;

          return Container(
            decoration: BoxDecoration(
              color: Colors.red,
              borderRadius: BorderRadius.circular(25),
            ),
            height: MediaQuery.of(context).size.height * 0.85,
            width: MediaQuery.of(context).size.width,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 15),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[
                      CarouselSlider(
                        items: imgList.map(
                          (item) 
                            return Container(
                              child: Container(
                                margin: EdgeInsets.all(5.0),
                                child: ClipRRect(
                                  borderRadius:
                                      BorderRadius.all(Radius.circular(5.0)),
                                  child: Stack(
                                    children: <Widget>[
                                      Image.network(
                                        item,
                                        fit: BoxFit.cover,
                                        height: 1000.0,
                                        width: 1000.0,
                                      ),
                                      Positioned(
                                        bottom: 0.0,
                                        left: 0.0,
                                        right: 0.0,
                                        child: Container(
                                          decoration: BoxDecoration(
                                            gradient: LinearGradient(
                                              colors: [
                                                Color.fromARGB(200, 0, 0, 0),
                                                Color.fromARGB(0, 0, 0, 0)
                                              ],
                                              begin: Alignment.bottomCenter,
                                              end: Alignment.topCenter,
                                            ),
                                          ),
                                        ),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                            );
                          ,
                        ).toList(),
                        options: CarouselOptions(
                          enlargeCenterPage: true,
                          enlargeStrategy: CenterPageEnlargeStrategy.height,
                          height: MediaQuery.of(context).size.height - 500,
                          aspectRatio: 2.0,
                          onPageChanged: (index, reason) 
                            setState(() 
                              _current = index;
                            );
                          ,
                        ),
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: imgList.map((url) 
                          return Container(
                            width: 8.0,
                            height: 8.0,
                            margin: EdgeInsets.symmetric(
                                vertical: 10.0, horizontal: 2.0),
                            decoration: BoxDecoration(
                              shape: BoxShape.circle,
                              color: _current == imgList.indexOf(url)
                                  ? Color.fromRGBO(0, 0, 0, 0.9)
                                  : Color.fromRGBO(0, 0, 0, 0.4),
                            ),
                          );
                        ).toList(),
                      ),
                      Text(
                        widget.name,
                        style: TextStyle(
                          fontSize: 30,
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      Text(
                        "United Kingdom",
                        style: TextStyle(
                          fontSize: 18,
                          color: Colors.white,
                        ),
                      ),
                    ],
                  ),
                )
              ],
            ),
          );
         else 
          return CircularProgressIndicator();
        
      ,
    );
  

【讨论】:

我认为使用它我已经设法让它在我可以接受你的答案之前得到一些工作,我在完成的情况下得到了这个错误。类型 'Future>' 不是类型转换中类型 'List' 的子类型。我相信这发生在设置状态 能否发布BottomSheetWidget_BottomSheetWidgetState 的更新代码示例? 完美,我已经根据更新的代码示例更新了我的答案。 嗯,试过了还是报错,我更新了上面的代码 抱歉,我错过了另一个问题,即您的 build 方法在所有情况下都没有返回小部件。

以上是关于颤动如何在初始化状态下使用未来的异步方法的主要内容,如果未能解决你的问题,请参考以下文章

Flutter应用打开时如何从sqlite数据库加载初始状态数据

如何在通量存储中异步加载初始状态?

ajax与jQuery的异步提交,他在啥情况下会走error

如何在初始化程序颤动中从小部件访问传递的值

如何使用获取的变量作为材料 UI 日期选择器的初始状态?

我应该如何将“redux-thunk”用于异步初始状态? (反应/减少)