Main.dart:
import 'package:flutter/material.dart';
import 'package:mypackage/widgets/home_widget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "My App",
theme: ThemeData(primarySwatch: Colors.blueGrey),
home: Home(),
);
}
}
Home.dart:
import 'package:flutter/material.dart';
import 'package:mypackage/widgets/secondary_page.dart';
import 'package:mypackage/widgets/home_view.dart';
import 'package:mypackage/widgets/settings_page.dart';
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomeState();
}
}
class _HomeState extends State<Home> {
int currentPageIndex = 0;
final List<Widget> pageWidgets = [HomeView(), SecondaryPage(), SettingsPage()];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My App"),
centerTitle: true,
),
body: pageWidgets[currentPageIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: currentPageIndex,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home), label: "Tab One"),
BottomNavigationBarItem(
icon: new Icon(Icons.account_balance), label: "Tab Two"),
BottomNavigationBarItem(
icon: new Icon(Icons.settings), label: "Tab Three"),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
// Update data from here
HomeView().updateDisplay();
}));
}
// Changes the index when the tapped page has loaded
void onTabTapped(int index) {
setState(() {
currentPageIndex = index;
});
}
}
HomeView.dart:
import 'package:flutter/material.dart';
import 'package:mypackage/models/mydisplay.dart';
import 'package:mypackage/network/mydata.dart';
class HomeView extends StatelessWidget {
final List<MyDisplay> dataList = [
new MyDisplay("Sample Display",
"SampleFile", 0),
];
Future<void> updateDisplay() async {
MyData myData = new MyData();
dataList.forEach((d) async {
d.changePercentage = await myData
.getDataPercentage("assets/data/" + d.fileName + ".xml");
print(d.dataName +
" change percentage: " +
d.changePercentage.toString() +
"%");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: new ListView.builder(
itemCount: dataList.length,
itemBuilder: (BuildContext context, int index) =>
buildCard(context, index)),
);
}
Widget buildCard(BuildContext context, int index) {
return Container(
child: Card(
color: Colors.teal.shade200,
child: Padding(
padding: const EdgeInsets.all(25),
child: Column(children: <Widget>[
Text(dataList[index].dataName,
style: new TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
Text(dataList[index].changePercentage.toString() + "%")
]))));
}
}
当我从updateDisplay()方法按预期的方式调用floatingActionButton ()时,数据会被打印到控制台,但是它似乎并没有更新实际的UI,卡片的内容,它们只是保持在初始的设置值。
为了澄清:如何从有状态小部件中更新listview (无状态小部件内)中卡片的内容?
很抱歉,如果这是一个重复的问题,我一直在寻找和继续寻找答案的问题,但我只是无法使它发挥作用。
发布于 2021-03-13 15:52:50
您需要使用有状态小部件,因为您不能更新无状态小部件。查看这链接以了解更多的information.The下一个问题,调用它,可以使用globalKeys修复。唯一奇怪的是,您必须将Home有状态小部件和HomeView有状态小部件保存在同一个省道文件中。。尝试使用此代码使其工作。
家庭视图
import 'package:flutter/material.dart';
import 'package:mypackage/widgets/secondary_page.dart';
import 'package:mypackage/widgets/settings_page.dart';
import 'package:mypackage/models/mydisplay.dart';
import 'package:mypackage/network/mydata.dart';
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomeState();
}
}
class _HomeState extends State<Home> {
int currentPageIndex = 0;
final List<Widget> pageWidgets = [HomeView(), SecondaryPage(), SettingsPage()];
GlobalKey<_HomeViewState> _myKey = GlobalKey();// We declare a key here
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("My App"),
centerTitle: true,
),
body: pageWidgets[currentPageIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: currentPageIndex,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home), label: "Tab One"),
BottomNavigationBarItem(
icon: new Icon(Icons.account_balance), label: "Tab Two"),
BottomNavigationBarItem(
icon: new Icon(Icons.settings), label: "Tab Three"),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
// Update data from here
_myKey.currentState.updateDisplay();//This is how we call the function
}));
}
// Changes the index when the tapped page has loaded
void onTabTapped(int index) {
setState(() {
currentPageIndex = index;
});
}
}
class HomeView extends StatefulWidget {
Function updateDisplay;
HomeView({Key key}): super(key: key);//This key is what we use
@override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
final List<MyDisplay> dataList = [
new MyDisplay("Sample Display",
"SampleFile", 0),
];
@override
void initState(){
super.initState();
widget.updateDisplay = () async {
MyData myData = new MyData();
dataList.forEach((d) async {
d.changePercentage = await myData
.getDataPercentage("assets/data/" + d.fileName + ".xml");
print(d.dataName +
" change percentage: " +
d.changePercentage.toString() +
"%");
});
setState((){});//This line rebuilds the scaffold
};
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: new ListView.builder(
itemCount: dataList.length,
itemBuilder: (BuildContext context, int index) =>
buildCard(context, index)),
);
}
Widget buildCard(BuildContext context, int index) {
return Container(
child: Card(
color: Colors.teal.shade200,
child: Padding(
padding: const EdgeInsets.all(25),
child: Column(children: <Widget>[
Text(dataList[index].dataName,
style: new TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
Text(dataList[index].changePercentage.toString() + "%")
]))));
}
}
我们使用setState((){})重建小部件。只要记住一个人的想法。无论您在哪里使用updateDisplay方法,都不要使它在重建后在循环中运行。就像。你可以在孩子的未来建筑中使用它。THat的方式它将继续重建
编辑
我们向HomeView添加了一个键,现在我们可以像_myKey.currentState.yourFunction
一样使用该键。希望我帮了忙
发布于 2021-03-13 17:15:05
虽然我理解你希望实现的目标,但我相信这将与“颤栗之路”背道而驰。您可以使用一个键实现您想要的结果,但是我相信,将状态提升到小部件树上会更容易,也更符合习惯。您可以在docs 这里中读到这方面的内容。
因此,在您的情况下,您可以将其更改为:
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomeState();
}
}
class _HomeState extends State<Home> {
int currentPageIndex = 0;
// Added this line
List<MyDisplay> dataList = [
new MyDisplay("Sample Display",
"SampleFile", 0),
];
final List<Widget> pageWidgets;
// moved the update function from HomeView to here
Future<void> updateDisplay() async {
MyData myData = new MyData();
dataList.forEach((d) async {
d.changePercentage = await myData
.getDataPercentage("assets/data/" + d.fileName + ".xml");
print(d.dataName +
" change percentage: " +
d.changePercentage.toString() +
"%");
});
setState((){});
}
@override
Widget build(BuildContext context) {
pageWidgets = [HomeView(dataList: dataList), SecondaryPage(), SettingsPage()]
return Scaffold(
appBar: AppBar(
title: Text("My App"),
centerTitle: true,
),
body: pageWidgets[currentPageIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: currentPageIndex,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home), label: "Tab One"),
BottomNavigationBarItem(
icon: new Icon(Icons.account_balance), label: "Tab Two"),
BottomNavigationBarItem(
icon: new Icon(Icons.settings), label: "Tab Three"),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
updateDisplay();
}));
}
// Changes the index when the tapped page has loaded
void onTabTapped(int index) {
setState(() {
currentPageIndex = index;
});
}
}
那么对于您的HomeView小部件:
class HomeView extends StatelessWidget {
HomeView({this.dataList});
final List<MyDisplay> dataList;
@override
Widget build(BuildContext context) {
return Scaffold(
body: new ListView.builder(
itemCount: dataList.length,
itemBuilder: (BuildContext context, int index) =>
buildCard(context, index)),
);
}
Widget buildCard(BuildContext context, int index) {
return Container(
child: Card(
color: Colors.teal.shade200,
child: Padding(
padding: const EdgeInsets.all(25),
child: Column(children: <Widget>[
Text(dataList[index].dataName,
style: new TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
Text(dataList[index].changePercentage.toString() + "%")
],
),
),
),
);
}
}
我还没测试过这个是否有效。我可能过一会儿再来。
发布于 2021-03-13 15:20:10
您需要在setState(() {});
之后调用HomeView().updateDisplay();
https://stackoverflow.com/questions/66615012
复制相似问题