Flutter 颤振:在父部件重建后未重建子部件

Flutter 颤振:在父部件重建后未重建子部件,flutter,dart,Flutter,Dart,版本: 颤振版本:1.12.14通道偏差 Dart版本:2.7.0 问题: 我想写一个待办事项应用程序。当我点击浮动按钮时,添加一个新的Todo,但在某些情况下,它不能很好地工作 Scaffold.body中的问题,详细信息在代码中 当我使用TodoPage(todoList:\u todoList)时,它工作得很好 \u pageList.elementAt(\u activeIndex)在我提交文本字段时不起作用 我发现print('Build Home')在提交后打印,但print('Bu

版本:
颤振版本:1.12.14通道偏差
Dart版本:2.7.0

问题:
我想写一个待办事项应用程序。当我点击浮动按钮时,添加一个新的Todo,但在某些情况下,它不能很好地工作

Scaffold.body
中的问题,详细信息在代码中

当我使用
TodoPage(todoList:\u todoList)
时,它工作得很好

\u pageList.elementAt(\u activeIndex)
在我提交文本字段时不起作用

我发现
print('Build Home')
在提交后打印,但
print('Build TodoPage')
未打印

为什么

我的代码:

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title: 'TodoList',
      home: Home(),
    );
  }
}


class Home extends StatefulWidget{
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home>{
  List<String> _todoList = ['a', 'b', 'c'];
  TextEditingController _controller;
  List<Widget> _pageList;
  int _activeIndex;
  Widget _curPage;

  @override
  void initState(){
    super.initState();
    _activeIndex = 0;
    _pageList = [TodoPage(todoList: _todoList,), OtherPage()];
    _curPage = _pageList[_activeIndex];
    _controller = TextEditingController();
  }

  @override
  Widget build(BuildContext context){
    print('build Home');
    return Scaffold(
      appBar: AppBar(title: Text('Todo'),),
      body: _pageList.elementAt(_activeIndex), // this is not work
      // body: TodoPage(todoList: _todoList,), // this is work well
      floatingActionButton: FloatingActionButton(
        onPressed: _openDlg,
        child: Icon(Icons.add),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.list), title: Text('Todo')),
          BottomNavigationBarItem(icon: Icon(Icons.favorite), title: Text('Other')),
        ],
        currentIndex: _activeIndex,
        selectedItemColor: Colors.blue,
        onTap: _onMenuTap,
      ),
    );
  }


  _onMenuTap(int index){
    setState(() {
      _activeIndex = index;
    });
  }

  _openDlg(){
    showDialog(
      context: context,
      builder: (BuildContext context){
        return SimpleDialog(
          children: <Widget>[
            TextField(
              controller: _controller,
            ),
            SimpleDialogOption(
              child: FloatingActionButton(child: Text('submit'), onPressed: _addTodo,),
            )
          ],
        );
      }
    );
  }

  _addTodo(){
    print(_controller.text);
    setState(() {
      _todoList.add(_controller.text);
    });
  }
}

class TodoPage extends StatefulWidget{
  TodoPage({Key key, this.todoList}): super(key: key);
  List<String> todoList;
  _TodoPageState createState() => _TodoPageState();
}

class _TodoPageState extends State<TodoPage>{

  @override
  void initState(){
    super.initState();
  }

  @override 
  Widget build(BuildContext context){
    print('build TodoPage');
    return Column(
      children: _buildTodoList(),
    );
  }

  List <Widget> _buildTodoList(){
    return widget.todoList.map((todo){
      return Text(todo, style: TextStyle(fontSize: 30),);
    }).toList();
  }
}


class OtherPage extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return Center(child: Text('Other Page'));
  }
}


导入“包装:颤振/材料.省道”;
void main()=>runApp(App());
类应用程序扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“托多利斯特”,
home:home(),
);
}
}
类Home扩展了StatefulWidget{
_HomeState createState()=>\u HomeState();
}
类(HomeState扩展状态){
列表_todoList=['a','b','c'];
TextEditingController\u控制器;
列表-页面列表;
int_活动索引;
小部件_curPage;
@凌驾
void initState(){
super.initState();
_activeIndex=0;
_页面列表=[TodoPage(todoList:_todoList,),OtherPage();
_curPage=_页面列表[_活动索引];
_控制器=文本编辑控制器();
}
@凌驾
小部件构建(构建上下文){
打印(“构建主页”);
返回脚手架(
appBar:appBar(标题:文本('Todo'),),
正文:\ u pageList.elementAt(\ u activeIndex),//这不起作用
//body:TodoPage(todoList:_todoList,),//这很好用
浮动操作按钮:浮动操作按钮(
按下按钮:_openDlg,
子:图标(Icons.add),
),
底部导航栏:底部导航栏(
项目:[
BottomNavigationBarItem(图标:图标(Icons.list),标题:文本('Todo')),
BottomNavigationBarItem(图标:图标(Icons.favorite),标题:文本(“其他”),
],
currentIndex:_activeIndex,
选择编辑颜色:Colors.blue,
onTap:_onMenuTap,
),
);
}
_onMenuTap(int索引){
设置状态(){
_activeIndex=index;
});
}
_openDlg(){
显示对话框(
上下文:上下文,
生成器:(BuildContext上下文){
返回SimpleDialog(
儿童:[
文本字段(
控制器:_控制器,
),
简单幻觉(
子:浮动操作按钮(子:文本('submit'),按下时:_addTodo,),
)
],
);
}
);
}
_addTodo(){
打印(_controller.text);
设置状态(){
_todoList.add(_controller.text);
});
}
}
类TodoPage扩展了StatefulWidget{
TodoPage({Key-Key,this.todoList}):super(Key:Key);
列出托多利斯特;
_TodoPageState createState()=>\u TodoPageState();
}
类_todopatate扩展状态{
@凌驾
void initState(){
super.initState();
}
@凌驾
小部件构建(构建上下文){
打印('buildtodopage');
返回列(
子项:_buildTodoList(),
);
}
列表_buildTodoList(){
返回widget.todoList.map((todo){
返回文本(todo,样式:TextStyle(fontSize:30),);
}).toList();
}
}
类OtherPage扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回中心(子:文本(“其他页面”);
}
}
这是合乎逻辑的

您正在重用
小部件的现有实例,小部件是不可变的。
因此,框架注意到小部件的实例没有改变,也没有调用
build
来优化性能

你的问题是,你违反了小部件不可变的规则,这使得这种优化破坏了你的应用程序

你所做的:

类MyState扩展状态{
SomeWidget myWidget=SomeWidget()…someProperty=“初始值”;
在某物上无效(){
设置状态(){
myWidget.someProperty=“新值”;
});
}
@凌驾
小部件构建(构建上下文){
返回myWidget;
}
}
你应该做的是:

类MyState扩展状态{
SomeWidget myWidget=SomeWidget(someProperty:“初始值”);
在某物上无效(){
设置状态(){
myWidget=SomeWidget(someProperty:“新值”);
});
}
@凌驾
小部件构建(构建上下文){
返回myWidget;
}
}

或者,根本不缓存小部件实例。

“return myWidget();”
SomeWidget
是否有
call()
方法?@pskink这只是一个输入错误,事实上,hahait也是我的第一个想法:-)如果在小部件构造函数中包含一个在调用something()后不同的键,这会更可靠. 使用UniqueKey()很容易做到这一点。@jwehrle:UniqueKey对我的用例非常有用,但我只是想知道使用它是否有任何副作用?