【问题标题】:Unable to set state with an external widget无法使用外部小部件设置状态
【发布时间】:2019-12-27 18:37:18
【问题描述】:

当我点击它时,我正在使用颤振并尝试更改图标的状态(切换图标)。如果一切都在同一个班级,这很好。但是我在重复的页面中重复了部分小部件,因此我已经将该小部件移到另一个类。现在,当我尝试通过传入一个函数来设置状态时,基于调试步骤,看起来它工作正常,但状态保持不变(图标没有改变)。我能知道我做错了什么吗?谢谢。

这是我从另一个类调用小部件并传入函数以设置状态的类。

class _MyPageState extends State<MyPage> {
  IconData heartStatus = FontAwesomeIcons.heart;

  void setFav(){
    print('clicked');
    setState(() {
      if (heartStatus == FontAwesomeIcons.heart) {
        heartStatus = FontAwesomeIcons.solidHeart;
      } else {
        heartStatus = FontAwesomeIcons.heart;
      }
    });
  }

  @override
  Widget build(BuildContext context) {

    Page page = new Page();
    PageController controller = PageController();

    return Scaffold(
      backgroundColor: Colors.blue,
      body: SafeArea(
        child: PageView(
          children: <Widget>[
            // this is the external widget repeated 3 times. Each time passing in setFav which is the setState function. 
            page.getPageData("text 1", "", setFav),
            page.getPageData("text 2", "", setFav),
            page.getPageData("text 3", "", setFav),
          ],
        ),
      ),
    );
  }
}

这是通过 page.getPageData 提供小部件的类(我已经删除了许多嵌套小部件,以专注于与此设置状态问题相关的图标)。

class Page{

  Widget getPageData(String question, String answer, Function setFav){
    IconData heartStatus = FontAwesomeIcons.heart;
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              GestureDetector(
                child: Icon(heartStatus),
                onTap: () {
                  setFav();
                },
              ),
              GestureDetector(
                child: Icon(FontAwesomeIcons.shareAlt),
                onTap: () {
                  print('shared');
                },
              ),
            ],
          ),
        ],
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    您正在提供setFav 方法,该方法调用setState 来更改MyPage 小部件中的图标。

    我认为您的目标是更改从getPageData 方法返回的小部件中的图标。

    使用setFav 方法更改MyPage 中的图标后,您没有使用此图标。您在 PageView 中的小部件没有使用该图标。

    我强烈建议您使用小部件,而不是函数。 https://iirokrankka.com/2018/12/11/splitting-widgets-to-methods-performance-antipattern/

    class Page extends StatelessWidget {
      Page({this.changeIcon, this.heartStatus});
    
      Function changeIcon;
      IconData heartStatus;
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  GestureDetector(
                    child: Icon(heartStatus),
                    onTap: () {
                      changeIcon();
                    },
                  ),
                  GestureDetector(
                    child: Icon(FontAwesomeIcons.shareAlt),
                    onTap: () {
                      print('shared');
                    },
                  ),
                ],
              ),
            ],
          ),
        );
      }
    }
    

    ...

    child: PageView(
              children: <Widget>[
                // this is the external widget repeated 3 times. Each time passing in setFav which is the setState function. 
                Page(heartStatus,setFav);
                Page(heartStatus,setFav);
                Page(heartStatus,setFav);
              ],
            ),
    

    【讨论】:

    • 尝试了您的建议,设置状态确实有效,但该状态会影响所有 3 个页面。如果我点击第一页,所有 3 页上的心脏都会变为实心。
    • 因为孩子与父母共享相同的状态。这是正确的行为。也许您可以保存 IconData 数组并通过索引传递 IconData。
    猜你喜欢
    • 2021-02-16
    • 1970-01-01
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2021-06-11
    • 2020-10-19
    相关资源
    最近更新 更多