首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从状态Widget更新无状态Widget

从状态Widget更新无状态Widget
EN

Stack Overflow用户
提问于 2021-03-13 15:08:58
回答 5查看 6.9K关注 0票数 1

Main.dart:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
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 (无状态小部件内)中卡片的内容?

很抱歉,如果这是一个重复的问题,我一直在寻找和继续寻找答案的问题,但我只是无法使它发挥作用。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2021-03-13 15:52:50

您需要使用有状态小部件,因为您不能更新无状态小部件。查看链接以了解更多的information.The下一个问题,调用它,可以使用globalKeys修复。唯一奇怪的是,您必须将Home有状态小部件和HomeView有状态小部件保存在同一个省道文件中。。尝试使用此代码使其工作。

家庭视图

代码语言:javascript
运行
复制
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一样使用该键。希望我帮了忙

票数 4
EN

Stack Overflow用户

发布于 2021-03-13 17:15:05

虽然我理解你希望实现的目标,但我相信这将与“颤栗之路”背道而驰。您可以使用一个键实现您想要的结果,但是我相信,将状态提升到小部件树上会更容易,也更符合习惯。您可以在docs 这里中读到这方面的内容。

因此,在您的情况下,您可以将其更改为:

代码语言:javascript
运行
复制
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小部件:

代码语言:javascript
运行
复制
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() + "%")
                ],
              ),
            ),
          ),
        );
  }
}

我还没测试过这个是否有效。我可能过一会儿再来。

票数 1
EN

Stack Overflow用户

发布于 2021-03-13 15:20:10

您需要在setState(() {});之后调用HomeView().updateDisplay();

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66615012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档