flutter 当我将回调从有状态小部件传递到无状态小部件时,为什么我的复选框没有更新?

yx2lnoni  于 2023-05-19  发布在  Flutter
关注(0)|答案(6)|浏览(212)

我试图使用提升状态为我的复选框,我知道通过改变我的TaskTile到一个有状态的小部件生病能够解决我的问题,但我想知道为什么我的复选框不更新时,我通过setstate作为回调从一个有状态的小部件。我很抱歉,如果这个问题是愚蠢的,我刚刚开始与Flutter所以任何帮助是感激的。
这是我的无状态小部件,它在磁贴中构建复选框

import 'package:flutter/material.dart';

class TaskTile extends StatelessWidget {
  final String title;
  final bool isChecked;
  final void Function(bool?) checkboxCallback;

  TaskTile({required this.title,required this.isChecked,required this.checkboxCallback});

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(title,style: TextStyle(decoration: isChecked?TextDecoration.lineThrough:null),),
      trailing: Checkbox(
        value: isChecked,
        onChanged: checkboxCallback,
      ),
    );
  }
}

这是一个有状态的小部件,我在这里给出回调

import 'package:flutter/material.dart';
import 'task_tile.dart';
import 'task.dart';

class TaskList extends StatefulWidget {
  @override
  _TaskListState createState() => _TaskListState();
}

class _TaskListState extends State<TaskList> {
  @override
  Widget build(BuildContext context) {
    bool isChecked = false;

    List<Task> tasks = [
      Task(title: 'Buy Milk', isDone: isChecked),
      Task(title: 'Buy Bread', isDone: isChecked),
      Task(title: 'Buy Eggs', isDone: isChecked),
    ];

    return ListView.builder(itemBuilder: (context, index) {
      return TaskTile(title: tasks[index].title,isChecked: tasks[index].isDone,checkboxCallback: (checkboxState){
        setState(() {
          tasks[index].toggleIsDone();
        });
      },);
    },itemCount: tasks.length,);
  }
}

这也是任务类,我给切换功能改变状态

class Task{
  final String title;
  bool isDone;

  Task({required this.title,required this.isDone});

  void toggleIsDone(){
    isDone = !isDone;
  }

}
sycxhyv7

sycxhyv71#

您没有调用该函数。而不是

trailing: Checkbox(
        value: isChecked,
        onChanged: checkboxCallback,
      ),

你能试试吗

trailing: Checkbox(
        value: isChecked,
        onChanged: (){checkboxCallback();},
      ),
uyto3xhc

uyto3xhc2#

您需要使TaskTile有状态。TaskList可以是StatelessWidget
答案如下:

import 'package:flutter/material.dart';

class TaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    bool isChecked = false;

    List<Task> tasks = [
      Task(title: 'Buy Milk', isDone: isChecked),
      Task(title: 'Buy Bread', isDone: isChecked),
      Task(title: 'Buy Eggs', isDone: isChecked),
    ];

    return ListView.builder(
      itemBuilder: (context, index) {
        return TaskTile(
          title: tasks[index].title,
          isChecked: tasks[index].isDone,
          checkboxCallback: (value) {
            tasks[index].toggleIsDone();
          },
        );
      },
      itemCount: tasks.length,
    );
  }
}

class TaskTile extends StatefulWidget {
  final String title;
  final bool isChecked;
  final Function checkboxCallback;

  TaskTile(
      {required this.title,
      required this.isChecked,
      required this.checkboxCallback,
      Key? key})
      : super(key: key);

  @override
  _TaskTileState createState() => _TaskTileState();
}

class _TaskTileState extends State<TaskTile> {
  late bool _isChecked;

  @override
  void initState() {
    super.initState();
    _isChecked = widget.isChecked;
  }

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        widget.title,
        style: TextStyle(
            decoration: _isChecked ? TextDecoration.lineThrough : null),
      ),
      trailing: Checkbox(
        value: _isChecked,
        onChanged: (value) {
          widget.checkboxCallback(value);
          setState(() {
            _isChecked = value!;
          });
        },
      ),
    );
  }
}

class Task {
  final String title;
  bool isDone;

  Task({required this.title, required this.isDone});

  void toggleIsDone() {
    isDone = !isDone;
  }
}
nom7f22z

nom7f22z3#

对于任何dynamic更改,您的widget class需要是stateful,如果您使用的是vscode,则可以轻松地从无状态更改为statful。首先悬停到你的statless小部件,然后你会得到一个灯泡一样的指示灯,按下它,然后你会得到一个改变状态的选项。

g6baxovj

g6baxovj4#

根据我的理解,您正在尝试更改列表中Task对象的状态(isChanged)。这个列表反过来用于listview builder中。由于flutter处理的是不可变的数据,并且您将列表的引用发送到listview构建器,因此列表中元素的更改不会反映在UI中,即使您使用了setState函数。相反,尝试创建一个与更新元素同名的新列表。这肯定会奏效的。
我的想法来自这个解决方案-https://stackoverflow.com/a/61847327/11844877
PS我是一个新手,不介意我的回答是没有帮助的。

ui7jx7zq

ui7jx7zq5#

这是从下面的链接的解决方案:

import 'package:flutter/material.dart';
class TaskList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    bool isChecked = false;
    List<Task> tasks = [
      Task(title: 'Buy Milk', isDone: isChecked),
      Task(title: 'Buy Bread', isDone: isChecked),
      Task(title: 'Buy Eggs', isDone: isChecked),
    ];
    return ListView.builder(
      itemBuilder: (context, index) {
        return TaskTile(
          title: tasks[index].title,
          isChecked: tasks[index].isDone,
          checkboxCallback: (value) {
            tasks[index].toggleIsDone();
          },
        );
      },
      itemCount: tasks.length,
    );
  }
}
class TaskTile extends StatefulWidget {
  final String title;
  final bool isChecked;
  final Function checkboxCallback;
  TaskTile(
      {required this.title,
      required this.isChecked,
      required this.checkboxCallback,
      Key? key})
      : super(key: key);
  @override
  _TaskTileState createState() => _TaskTileState();
}
class _TaskTileState extends State<TaskTile> {
  late bool _isChecked;
  @override
  void initState() {
    super.initState();
    _isChecked = widget.isChecked;
  }
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        widget.title,
        style: TextStyle(
            decoration: _isChecked ? TextDecoration.lineThrough : null),
      ),
      trailing: Checkbox(
        value: _isChecked,
        onChanged: (value) {
          widget.checkboxCallback(value);
          setState(() {
            _isChecked = value!;
          });
        },
      ),
    );
  }
}
class Task {
  final String title;
  bool isDone;
  Task({required this.title, required this.isDone});
  void toggleIsDone() {
    isDone = !isDone;
  }
}

https://codeutility.org/why-is-my-checkbox-not-updating-when-i-pass-a-callback-from-a-stateful-widget-to-stateless-widget/

uz75evzq

uz75evzq6#

tasks_tile.dart文件:

import 'package:flutter/material.dart';

class TaskTile extends StatelessWidget {
  final bool isChecked;
  final String TaskTitle;
  final Function(bool?) CheckboxCallback;

  TaskTile(
      {required this.isChecked,
      required this.TaskTitle,
      required this.CheckboxCallback});

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        '$TaskTitle',
        style: TextStyle(
            decoration: isChecked ? TextDecoration.lineThrough : null),
      ),
      trailing: Checkbox(
        activeColor: Colors.red.shade800,
        value: isChecked,
        onChanged: CheckboxCallback,
      ),
    );
  }
}

tasks_list.dart文件:

import 'package:flutter/material.dart';
import 'package:todoey/widgets/tasks_tile.dart';
import 'package:todoey/models/task.dart';

class TasksList extends StatefulWidget {
  final List<Task> tasks;

  TasksList(this.tasks);

  @override
  State<TasksList> createState() => _TasksListState();
}

class _TasksListState extends State<TasksList> {

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: (context, index) {
        return TaskTile(
          TaskTitle: widget.tasks[index].name,
          isChecked: widget.tasks[index].isDone,
          CheckboxCallback: (bool? checkBoxState) {
            setState(
              () {
                widget.tasks[index].toggleDone();
              },
            );
          },
        );
      },
      itemCount: widget.tasks.length,
    );
  }
}

这里是解决方案,为我工作,增加布尔?在括号的final Function(bool?)checkboxCallback;'并在tasks_list.dart文件中的checkboxCallback中添加'checkboxCallback:(bool?checkBoxState){},.

相关问题