setState并不更新用户界面[英] setState doesn't update the user interface

本文是小编为大家收集整理的关于setState并不更新用户界面的处理方法,想解了setState并不更新用户界面的问题怎么解决?setState并不更新用户界面问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我在使用有状态小部件时遇到了一些与 setState 函数相关的问题,这些小部件在定时器的帮助下自行更新.下面的代码显示了 2 个主要类,它们复制了我是如何发现这个错误的.文本小部件"Lorem"应在 10 秒内插入 - 确实如此 - 但从未显示.我尝试调试数组"Items",它确实在 5 秒后包含"lorem"文本小部件,这是应该的."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",会发生什么在列表中,但不在 UI 中.

推荐答案

问题如下:

  • State 不应该有任何构造函数参数.使用 widget 属性来访问关联 StatefulWidget 的最终属性.
  • Flutter 正在重用您的 _textClass 实例,因为类名和键匹配.这是一个问题,因为您只在 initState 中设置了 widget.word,因此您没有获取新的 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<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();
}

class _textClass extends State<textClass>
    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);
  }
}

本文地址:https://www.itbaoku.cn/post/1793890.html