首页 > 解决方案 > Flutter Stateful 小部件不会重建

问题描述

提前感谢您的帮助,我有一个基本上是 TODO 应用程序的应用程序,这里的问题是我有一个字符串类型的列表,用户将在其中放置他需要做的任务,这就是为什么我尝试做的是检查列表何时仍然为空,显示一个带有图像的列,如果用户添加一个项目,则列表不再为空,所以它显示列表而不是列,因为我做了一个方法中的简单 if buildscreen()。问题:将新项目添加到我的列表后的小部件即使在调用 setState 后也不会再次重建addTask(),因此它看不到列表是满的还是空的,它会继续显示带有图像的列。

这是代码

 import 'package:flutter/material.dart';
import 'package:todo_app/custom_icons_icons.dart';

class Todo extends StatefulWidget {
  @override
  _TodoState createState() => _TodoState();
}

List<String> tasks = [];
var hour= DateTime.now().hour;
int listlength= tasks.length;



class _TodoState extends State<Todo> {
  GlobalKey<AnimatedListState> globalKey= new GlobalKey<AnimatedListState>();
  void addTask(String text){
    print("Add task is built");
    setState(() {
      tasks.insert(0,text);
      globalKey.currentState.insertItem(0);


    });



  }

  void removeTask(int index){
setState(() {
  globalKey.currentState.removeItem(index, (context,animation){
    return SizedBox(width: 0, height: 0);

  });
  tasks.removeAt(index);

});
  }

  Widget promptRemove(int index){
    showDialog(context: context,
    builder: (BuildContext builder){
     return AlertDialog(
       title: Text("Do you want to mark ${tasks[index]} as done?"),
       actions: [
          FlatButton(onPressed:() {
            removeTask(index);
            Navigator.pop(context);
          }
              , child: Text("Mark as Done")),
         FlatButton(onPressed:(){
           Navigator.pop(context);
         }, child: Text("Cancel"))

       ],
      );
    }
    );
  }

  Widget buildItem(String text, int index){
    return Dismissible(
      key: Key("${text.hashCode}"),
      onDismissed: (direction)=> removeTask(index),
      direction: DismissDirection.startToEnd,
      child: Card(
        elevation: 4,
        child: ListTile(
          leading: Container(
              margin: EdgeInsets.only(
                top: 5
              ),
              child: Container(

                  child: Icon(Icons.lightbulb, size: 30, color: Colors.blue,))),
          title: Text(text),
          subtitle: Text("Today"),
          trailing: Icon(Icons.arrow_forward_ios_rounded, color: Colors.blue,),
        ),
      ),
    );
  }
  
  Widget buildList(){
    return AnimatedList(
      key: globalKey,
      initialItemCount: tasks.length,
      itemBuilder: (BuildContext context, int index, animation){
        return SlideTransition(
            position: Tween<Offset>(
              begin: const Offset(-1, 0),
              end: Offset(0, 0),
            ).animate(CurvedAnimation(
                parent: animation,
                curve: Curves.bounceIn,
                reverseCurve: Curves.bounceOut)),
            child: buildItem(tasks[index], index));
        }
        );
    
  }
  Widget buildscreen(){
    print("Screen is built");
    if(tasks.isEmpty){
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              child: Image.asset("assets/images/3327598.jpg"),
            ),
            Text("Add tasks and start beign producivity "),
            SizedBox(height: 100,)
          ],
        ),
      );
    }else{
      return buildList();
    }

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        centerTitle: true,
        elevation: 0,
        backgroundColor: Colors.transparent,
        actions: [
          ((){
            if(hour>6 && hour<18){
              return Container(
                  margin: EdgeInsets.only(
                    right: 20
                  ),
                  child: Icon(CustomIcons.cloud_sun, color: Colors.blue,size: 28,));
            } else {
              return Container(
                  margin: EdgeInsets.only(
                    right: 20
                  ),
                  child: Icon(CustomIcons.cloud_moon, color: Colors.blue,size: 28,));

            }

          }())
        ],
        leading: Container(
          width: 10,
          height: 10,
          margin: EdgeInsets.only(
            top: 10,
            left: 10,
            right: 10,
            bottom: 10
          ),
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadiusDirectional.circular(30)
          ),
          child: Center(child: Text("${tasks.length}")),
        ),
        title: Text("Todo App",style: TextStyle(color: Colors.blue),),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed:(){
          Navigator.of(context).push(
            new MaterialPageRoute(builder: (BuildContext context){
              return Scaffold(
                backgroundColor: Colors.white,
                appBar: AppBar(

                  title: Text("Add a task"),
                ),
                body: TextField(
                  onSubmitted:(val){
                    addTask(val);
                    Navigator.of(context).pop();


                  },
                ),
              );
            })
          );
        },
        child: Icon(Icons.add),
      ),
      body: buildscreen()


      );
  }
}

标签: flutterdart

解决方案


问题是您没有检查 globalKey.currentState 是否为空,然后在 AnimatedList 小部件中对新项目的介绍进行动画处理。只需在插入 globalKey.currentState.insertItem(0) 之前添加以下检查。

if (globalKey.currentState != null)

这将确保您不会在小部件重建时插入项目,并且您将等待状态可用。添加此行后,您的 addTask() 方法应如下所示:

  void addTask(String text) {
    print("Add task is built");
    setState(() {
      tasks.insert(0, text);
      if (globalKey.currentState != null) globalKey.currentState.insertItem(0);
    });
  }

推荐阅读