Flutter,如何在有状态小部件中正确声明和使用变量?

如何解决Flutter,如何在有状态小部件中正确声明和使用变量?

我有一个 StatefulWidget,其中包含一个带有 ListView()ListView.builder()ListView.builder() 使用两个列表构建多个 CheckBoxListTile()一个用于标签一个用于布尔值。但是,它没有按预期工作。我试图创建一个问题的最小示例,它看起来像这样:

import 'package:Flutter/material.dart';

class TestClass extends StatefulWidget {
  @override
  _TestClassstate createState() => _TestClassstate();
}

class _TestClassstate extends State<TestClass> {
  @override
  Widget build(BuildContext context) {
    bool firstBoolean = false;
    bool secondBoolean = false;
    List labels = [
    "First CheckBox","Second CheckBox",];  
    List<bool> booleans = [
      firstBoolean,secondBoolean,];    
    return ListView(
      children: [
        Container(
          height: MediaQuery.of(context).size.height * 0.5,child: ListView.builder(
              physics: AlwaysScrollableScrollPhysics(),shrinkWrap: true,itemCount: 2,itemBuilder: (context,index) {
                return CheckBoxListTile(
                  title: Text("${labels[index]}"),value: booleans[index],onChanged: (bool newValue) {
                    setState(() {
                      secondBoolean = newValue;
                      print(
                          "firstBoolean,secondBoolean: [$firstBoolean,$secondBoolean]");
                    });
                  },);
              }),),],);
      }
    }

这不会更改复选框,也不会更改分配的布尔值。如果我替换这一行:

value: booleans[index]

value: firstBoolean

然后将 bool firstBoolean = false; 移动到 @override 中的 _TestCassstate 上方它“有效”但由于现在所有复选框都分配了相同的布尔变量,因此在同时。但我不明白为什么这个“有效”而上面的代码却没有。此外,如果我尝试在 @override 上方创建我需要的所有布尔值,然后尝试创建包含所有这些的列表,我会收到此错误

实例成员 'firstBoolean' 不能在 初始化程序。尝试用 a 替换对实例成员的引用 不同的表达

如果我使用 @override 上方的标签移动到 List,它不会给我这个错误并正确分配标签

我觉得我没有理解 StatefulWidgets 的一些基本知识。因此,如果有人能给我解释如何正确解决这个问题以及为什么这不能按预期工作,我真的很感激

解决方法

每当您调用 setstate() 时,都会调用 build 方法,并在 build 方法中声明您。

覆盖 initState() 状态方法。

class _TestClassState extends State<TestClass> {
   bool firstBoolean,secondBoolean;
   List labels;
   List<bool> booleans;
  
  @override
   void initState(){
    super.initState();
       firstBoolean = false;
     secondBoolean = false;
     labels = [
    "First Checkbox","Second Checkbox",];  
    booleans = [
      firstBoolean,secondBoolean,];    
  }
}

并从构建方法中删除变量声明

,

您甚至不需要单独的 bool 变量。

您基本上可以将您的 labels 放在您的 TestClass 中,因为它们不是状态的一部分,因为它们永远不会改变。

接下来,您可以在 List<bool> booleans 类中只使用 State,因为所有更改的内容都只是这些 booleans 本身。

所以你的结构现在会是这样。

class TestClass extends StatefulWidget {
  final List labels = [
    "First Checkbox",];
  
  @override
  _TestClassState createState() => _TestClassState();
}

这是将它们放入 StatefulWidget 类的好习惯。然后,您可以像这样在 State 类中使用它们 - widget.labels[index]

因此,您的 State 类将是,

class _TestClassState extends State<TestClass> {
  List<bool> booleans = [false,false];

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Container(
          height: MediaQuery.of(context).size.height * 0.5,child: ListView.builder(
            physics: AlwaysScrollableScrollPhysics(),shrinkWrap: true,itemCount: 2,itemBuilder: (context,index) {
              return CheckboxListTile(
                title: Text("${widget.labels[index]}"),value: booleans[index],onChanged: (bool newValue) {
                  setState(() {
                    // There was a logic error here in your code,so changed it to work correctly
                    booleans[index] = newValue;
                });
              },);
          }),),],);
  }
}

enter image description here

,

每当您调用 setState() 方法时,都会调用构建函数并使用相同的旧值初始化变量。 解决您的问题的最简单方法是将变量保留在构建函数之外,这样每次调用 setState() 方法时它们就不会被初始化。 这是你应该做的

    import 'package:flutter/material.dart';
class TestClass extends StatefulWidget {
  @override
  _TestClassState createState() => _TestClassState();
}

class _TestClassState extends State<TestClass> {
    // Declare the variables above build fucntion
    bool firstBoolean = false; 
    bool secondBoolean = false;
    List labels = [
    "First Checkbox",];  
    List<bool> booleans = [false,false];    
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Container(
          height: MediaQuery.of(context).size.height * 0.5,child: ListView.builder(
              physics: AlwaysScrollableScrollPhysics(),index) {
                return CheckboxListTile(
                  title: Text("${labels[index]}"),onChanged: (bool newValue) {
                    setState(() {
                      secondBoolean = newValue;
                      print(
                          "firstBoolean,secondBoolean: [$firstBoolean,$secondBoolean]");
                    });
                  },);
              }),);
      }
    }
,

您在错误的地方声明了变量,您已经在构建函数中初始化了这些变量。因此,每当您调用 setState 时,变量都会重新初始化为默认值。此外,您不需要使用 firstBooleansecondBoolean。将您的代码更改为:

class TestClass extends StatefulWidget {
  @override
  _TestClassState createState() => _TestClassState();
}

class _TestClassState extends State<TestClass> {

  List labels = [
    "First Checkbox",];
  List<bool> booleans = List.filled(2,false); // Initialising with default value

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Container(
          height: MediaQuery.of(context).size.height * 0.5,index) {
              return CheckboxListTile(
                title: Text("${labels[index]}"),onChanged: (bool newValue) {
                  setState(() {
                    booleans[index] = newValue;
                    print(booleans[index]);
                  });
                },);
            },);
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?