【问题标题】:State recreates again when softkeyboard appears出现软键盘时再次重新创建状态
【发布时间】:2019-12-02 14:49:46
【问题描述】:

我有一个使用 FutureBuilder 显示信息的应用。

当我打开 Textfield 时,会出现软键盘,并重新创建 FutureBuilder 的状态。有什么办法可以避免不必要地运行构建方法。

显然,当我使用初始化状态调用未来时,它可以工作,但对于删除数据等其他功能,它不起作用,因为未来只会被调用一次。

这是我的代码

         class FutureBuilderWidget extends StatefulWidget {
          @override
          _FutureBuilderWidgetState createState() => _FutureBuilderWidgetState();
        }

        class _FutureBuilderWidgetState extends State<FutureBuilderWidget> {
          final _appBar = AppBar();

          @override 
          Widget build(BuildContext context) {
            return FutureBuilder(
                      future: Provider.of<QuickNotesProvider>(context, listen: false)
                          .fetchAndSetNotes(),
                      builder: (ctx, snapshot) {
                        return snapshot.connectionState == ConnectionState.waiting
                            ? Center(
                                child: Text('loading...'),
                              )
                            : Consumer<QuickNotesProvider>(
                                child: Center(
                                  child: Container(
                                    margin: EdgeInsets.only(
                                        top: MediaQuery.of(context).size.height * 0.3),
                                    child: Column(
                                      children: <Widget>[
                                        Icon(Icons.calendar_today,
                                            size: MediaQuery.of(context).size.height *
                                                0.07),
                                        SizedBox(
                                          height: 6,
                                        ),
                                        Text('Added Notes will appear here',
                                            style:
                                                Theme.of(context).textTheme.headline),
                                        SizedBox(
                                          height: 10,
                                        ),
                                        Text(
                                          'Tap + to add a quick note',
                                          style: TextStyle(
                                              fontSize:
                                                  MediaQuery.of(context).size.height *
                                                      0.02,
                                              fontWeight: FontWeight.w400),
                                        )
                                      ],
                                    ),
                                  ),
                                ),
                                builder: (ctx, eventData, ch) {
                                  if (eventData.quicknotes.length == 0) {
                                    return ch;
                                  } else {
                                    return Container(
                                      height: (MediaQuery.of(context).size.height -
                                              _appBar.preferredSize.height -
                                              MediaQuery.of(context).padding.top -
                                              MediaQuery.of(context).padding.bottom) *
                                          0.869,
                                      child: ListView.builder(
                                        itemCount: eventData.quicknotes.length,
                                        itemBuilder: (context, index) {
                                          return Container(
                                              margin: const EdgeInsets.only(
                                                  left: 10, top: 7, right: 10),
                                              child: Card(
                                                elevation: 5,
                                                shape: RoundedRectangleBorder(
                                                    borderRadius:
                                                        BorderRadius.circular(5)),
                                                color: Color.fromRGBO(230, 230, 230, 1),
                                                child: Column(
                                                  crossAxisAlignment:
                                                      CrossAxisAlignment.start,
                                                  children: <Widget>[
                                                    Padding(
                                                      padding: EdgeInsets.only(
                                                          top: 10, left: 8),
                                                      child: Text(
                                                        eventData.quicknotes[index]
                                                            .quicknote,
                                                      ),
                                                    ),
                                                    Row(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment.end,
                                                      children: <Widget>[
                                                        Padding(
                                                          padding:
                                                              const EdgeInsets.only(
                                                                  right: 10.0),
                                                          child: InkWell(
                                                            onTap: () {
                                                              setState(() {
                                                                eventData.deleteEvents(
                                                                    eventData
                                                                        .quicknotes[
                                                                            index]
                                                                        .id);
                                                              });
                                                            },
                                                            child: Icon(
                                                              Icons.more_horiz,
                                                              color: Colors.black54,
                                                            ),
                                                          ),
                                                        )
                                                      ],
                                                    )
                                                  ],
                                                ),
                                              ));
                                        },
                                      ),
                                    );
                                  }
                                });
                      },
                    );
          }
        }

【问题讨论】:

标签: flutter dart


【解决方案1】:

这很正常。当软键盘出现时,您的布局会调整大小,因此会重新构建。

您可以通过在小部件的 Scaffold 祖先中设置 resizeToAvoidBottomInsets 来避免调整大小,但如果发生任何重建,问题就会出现。

处理此问题的一种方法是缓存您的Future 结果。 我相信您可以使用Completer 来防止重新执行。

在你的State 创建一个

var myCompleter = Completer<YourDataDype>()

然后在initState 中启动你的未来函数,但不要返回结果,而是这样做:

myCompleter.complete(yourData)

然后您可以将myCompleter.future 传递给您的FutureBuilder 看看会发生什么。

我个人从未这样做过,因为我使用 BLoC pattern 将逻辑和表示分开,但它确实适用于您的情况。

你也应该开始拆分你的逻辑,因为它会避免很多痛苦并提高你的代码库质量!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多