问题描述
基本上,我正在尝试制作一个应用程序,其内容将通过从网站获取信息的异步函数进行更新,但是当我尝试设置新状态时,它不会重新加载新内容.如果我调试该应用程序,则表明当前内容是新的内容,但是在"重建"整个小部件之后,它不会显示新信息.
编辑: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), ); } }