一尘不染

setState不会更新用户界面

flutter

我在使用有状态的小部件时遇到了一些与setState函数有关的问题,这些小部件在计时器的帮助下进行了自我更新。
下面的代码显示了2个主要类,它们复制了我如何找到此错误的方法。该文本组件“排版”应该在10秒内插入-这是- ,但它从来没有显示。我试图调试数组“ Items”,并且 在5秒钟后确实包含
“ lorem” Text Widget,这是应该的。“ build”功能可以运行,但在UI中没有任何区别。

class textList extends StatefulWidget {

  @override
  State<StatefulWidget> createState() =>
      new _textListState();
}

class _textListState extends State<textList>
    with TickerProviderStateMixin {

  List<Widget> items = new List();
  Widget lorem = new textClass("Lorem");
  Timer timer;

  @override
  void initState() {
    super.initState();

    items.add(new textClass("test"));
    items.add(new textClass("test"));

    timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
      setState(() {
        items.removeAt(0);
        items.add(lorem);
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    timer.cancel();
  }

  @override
  Widget build(BuildContext context) {
    Iterable<Widget> content = ListTile.divideTiles(
        context: context, tiles: items).toList();

    return new Column(
      children: content,
    );
  }
}

class textClass extends StatefulWidget {
  textClass(this.word);

  final String word;

  @override
  State<StatefulWidget> createState() =>
      new _textClass(word);
}

class _textClass extends State<textClass>
    with TickerProviderStateMixin {
  _textClass(this.word);

  String word;
  Timer timer;

  @override
  void initState() {
    super.initState();

    timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
      setState(() {
        word += "t";
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    timer.cancel();
  }


  @override
  Widget build(BuildContext context) {
    return new Text(word);
  }
}

这不是我发现此错误的方式,但这是复制它的最简单方法。主要思想是:子文本应该不断更新自身(在这种情况下,最后要添加“ t”),并且在5秒钟后,
应将其最后一个替换为文本小部件“ Lorem”,这会发生什么情况在列表中,但不在用户界面中。


阅读 311

收藏
2020-08-13

共1个答案

一尘不染

这是怎么回事:

  • A State绝对不能有任何构造函数参数。使用该widget属性可以访问关联的的最终属性StatefulWidget
  • Flutter正在重用您的_textClass实例,因为类名和键匹配。这是一个问题,因为您仅进行了设置widget.wordinitState因此您不会选择新的word配置信息。您可以通过为StatefulWidget实例提供唯一的键来消除它们的歧义并导致旧State的东西被处置来解决此问题,或者可以保留旧的东西State并加以实施didUpdateWidget。后一种方法如下所示。

    import ‘dart:async’;
    import ‘package:flutter/material.dart’;

    void main() {
    runApp(new MaterialApp(
    home: new Scaffold(
    appBar: new AppBar(title: new Text(‘Example App’)),
    body: new textList(),
    ),
    ));
    }

    class textList extends StatefulWidget {

    @override
    State createState() =>
    new _textListState();
    }

    class _textListState extends State
    with TickerProviderStateMixin {

    List items = new List();
    Widget lorem = new textClass(“Lorem”);
    Timer timer;

    @override
    void initState() {
    super.initState();

    items.add(new textClass("test"));
    items.add(new textClass("test"));
    
    timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) {
      setState(() {
        items.removeAt(0);
        items.add(lorem);
      });
    });
    

    }

    @override
    void dispose() {
    super.dispose();
    timer.cancel();
    }

    @override
    Widget build(BuildContext context) {
    Iterable content = ListTile.divideTiles(
    context: context, tiles: items).toList();

    return new Column(
      children: content,
    );
    

    }
    }

    class textClass extends StatefulWidget {
    textClass(this.word);

    final String word;

    @override
    State createState() =>
    new _textClass();
    }

    class _textClass extends State
    with TickerProviderStateMixin {
    _textClass();

    String word;
    Timer timer;

    @override
    void didUpdateWidget(textClass oldWidget) {
    if (oldWidget.word != widget.word) {
    word = widget.word;
    }
    super.didUpdateWidget(oldWidget);
    }

    @override
    void initState() {
    super.initState();
    word = widget.word;

    timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) {
      setState(() {
        word += "t";
      });
    });
    

    }

    @override
    void dispose() {
    super.dispose();
    timer.cancel();
    }

    @override
    Widget build(BuildContext context) {
    return new Text(word);
    }
    }

2020-08-13