Flutter - setState 不更新内部有状态小部件[英] Flutter - setState not updating inner Stateful Widget

本文是小编为大家收集整理的关于Flutter - setState 不更新内部有状态小部件的处理方法,想解了Flutter - setState 不更新内部有状态小部件的问题怎么解决?Flutter - setState 不更新内部有状态小部件问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

基本上,我正在尝试制作一个应用程序,其内容将通过从网站获取信息的异步​​函数进行更新,但是当我尝试设置新状态时,它不会重新加载新内容.如果我调试该应用程序,则表明当前内容是新的内容,但是在"重建"整个小部件之后,它不会显示新信息.

编辑:LoadData()方法,基本上是用HTTP软件包读取URL,URL包含一个JSON文件,其内容每5分钟随着新闻而更改一次.例如,一个带有运动实时记分板的.json文件,其分数总是在变化,因此内容应始终随新结果而变化.

class mainWidget extends StatefulWidget
{    
  State<StatefulWidget> createState() => new mainWidgetState();
}

class mainWidgetState extends State<mainWidget>
{

  List<Widget> _data;
  Timer timer;

  Widget build(BuildContext context) {
     return new ListView(
              children: _data);
  }

  @override
  void initState() {
    super.initState();
    timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) async {
      String s = await loadData();
      this.setState(() {
        _data = <Widget> [new childWidget(s)];
      });
      });
  }
}

class childWidget extends StatefulWidget {
  childWidget(String s){
    _title = s;
  }

  Widget _title;

  createState() => new childState();
}

class childState extends State<gameCardS> {

  Widget _title;

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(onTap: foo(),
       child: new Card(child: new Text(_title));

  }

  initState()
  {
    super.initState();
    _title = widget._title;
  }
}

推荐答案

这应该解决您的问题.基本上,您始终希望在build方法层次结构中创建小部件.

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(home: new Scaffold(body: new MainWidget())));

class MainWidget extends StatefulWidget {
    @override
    State createState() => new MainWidgetState();
}

class MainWidgetState extends State<MainWidget> {

    List<ItemData> _data = new List();
    Timer timer;

    Widget build(BuildContext context) {
        return new ListView(children: _data.map((item) => new ChildWidget(item)).toList());
    }

    @override
    void initState() {
        super.initState();
        timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) async {
            ItemData data = await loadData();
            this.setState(() {
                _data = <ItemData>[data];
            });
        });
    }


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

    static int testCount = 0;

    Future<ItemData> loadData() async {
        testCount++;
        return new ItemData("Testing #$testCount");
    }
}

class ChildWidget extends StatefulWidget {

    ItemData _data;

    ChildWidget(ItemData data) {
        _data = data;
    }

    @override
    State<ChildWidget> createState() => new ChildState();
}

class ChildState extends State<ChildWidget> {

    @override
    Widget build(BuildContext context) {
        return new GestureDetector(onTap: () => foo(),
            child: new Padding(
                padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 24.0),
                child: new Card(
                    child: new Container(
                        padding: const EdgeInsets.all(8.0),
                        child: new Text(widget._data.title),
                    ),
                ),
            )
        );
    }

    foo() {
        print("Card Tapped: " + widget._data.toString());
    }
}

class ItemData {
    final String title;

    ItemData(this.title);

    @override
    String toString() {
        return 'ItemData{title: $title}';
    }
}

其他推荐答案

这确实让我头疼,没有Google的结果工作.最终奏效的是如此简单.在您的孩子build()中,将值分配给本地变量,然后再返回.一旦我做到这一点,一切都与后续数据负载一起使用.我什至取出了initstate()代码.

非常感谢@simon.您的答案以某种方式激发了我尝试.

在您的孩子中:

@override
Widget build(BuildContext context) {
_title = widget._title; // <<< ADDING THIS HERE IS THE FIX
return new GestureDetector(onTap: foo(),
   child: new Card(child: new Text(_title));

}

希望这可以在您的代码中起作用.对我来说,我使用一张地图来用于传递的整个JSON记录,而不是一个字符串,但仍然可以工作.

其他推荐答案

根问题解释

  • initState() ,对于儿童窗口当小部件插入树上时,只有一次一次.因此,您的孩子小部件变量将在父窗口上更改时永远不会更新.从技术上讲,小部件的变量正在发生变化,您只是没有捕获州类的变化.

  • build() 每次小部件中的某些东西都会发生变化.这就是 @gregthegeek 解决方案的原因.更新孩子小部件的构建方法中的变量将确保它们从父母那里获得最新信息.

作品

class ChildState extends State<ChildWidget> {
    late String _title;
    @override
    Widget build(BuildContext context) {
        _title = widget._title; // <==== IMPORTANT LINE
        return new GestureDetector(onTap: () => foo(),
            child: new Text(_title),
        );
    }
}

不起作用

(当_title更改父时,它不会更新)

class ChildState extends State<ChildWidget> {
    late String _title;

    @override
    void initState() {
      super.initState();
      _title = widget._title; // <==== IMPORTANT LINE
    }

    @override
    Widget build(BuildContext context) {
        return new GestureDetector(onTap: () => foo(),
            child: new Text(_title),
        );
    }
}

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