简单的 DropdownButton 不适用于新页面路由抖动

Simple DropdownButton not working on new page route flutter

我的应用程序很简单。

我有一个主页,您可以在其中按一个按钮打开一个新的 MaterialPageRoute。

在这个新的页面路由中,我有一个基本的下拉菜单。

问题是,当我点击下拉菜单时,出现此错误:

setState() or markNeedsBuild() called when widget tree was locked.
This Navigator widget cannot be marked as needing to build because the framework is locked.

下拉列表是 "FilterPage" class 的成员。只有当我将 FilterPage 放在新页面路由中时才会发生错误。例如,如果我使用新的 FilterPage() 作为主页,一切都会完美无缺。

复制此代码的所有代码如下。谢谢你看这个!

import 'package:flutter/material.dart';

final Map<String,String> categoryLookup = {
  "business":"Accounting/Business",
  "science":"Science",
  "technology":"Technology"
};

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Link',
      home: new Home(),
      routes: <String, WidgetBuilder> {
        '/filter': (BuildContext context) => new FilterPage(),
      },
    );
  }

}

class Home extends StatefulWidget {
  @override
  createState() => new HomeState();
}

class HomeState extends State<Home> {

  @override
  Widget build(BuildContext context){
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Browse Jobs'),
        actions: <Widget>[
          new IconButton(
            icon: new Icon(Icons.search),
            onPressed: () => Navigator.of(context).pushNamed('/filter'),
          ),
        ],
      ),
      body: new Center(
        child: new Text("Home"),
      ),
    );
  }

}

class FilterPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final GlobalKey<MyDropDownState> categoryKey = new GlobalKey<MyDropDownState>();
    final MyDropDown categoryDropdown = new MyDropDown(key: categoryKey, itemMap: categoryLookup);

    print("key: "+ categoryKey.toString());

    return new Scaffold(
      appBar : new AppBar(
        title: new Text('Filter Jobs'),
        actions: <Widget>[
          new IconButton(
            icon: new Icon(Icons.refresh),
            onPressed: () {
              print('Will reset dropdown using key');
            },
          ),
        ],
      ),
      body: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Column(
          children: <Widget>[
            categoryDropdown,
          ],
        ),
      ),
    );
  }
}

class MyDropDown extends StatefulWidget {

  MyDropDown({
    Key key,
    this.itemMap
  }) : super(key:key);

  final Map<String, String> itemMap;

  @override
  MyDropDownState createState() => new MyDropDownState();

}

class MyDropDownState extends State<MyDropDown> {

  String _selection;

  @override
  Widget build(BuildContext context) {
    return new DropdownButton(
      value: _selection,
      items: getDropItems(widget.itemMap),
      onChanged: (s) {
        setState(() {
          _selection = s;
        });
      },
      hint: new Text('None'),
    );
  }

  List<DropdownMenuItem> getDropItems(Map<String, String> itemMap){
    final List<DropdownMenuItem> itemList = [];
    itemMap.forEach(
        (key,value){
          itemList.add(new DropdownMenuItem<String>(value: key, child: new Text(value)));
        }
    );
    return itemList;
  }

}

要解决您的问题,请更改

class FilterPage extends StatelessWidget {

@override
Widget build(BuildContext context) {
final GlobalKey<MyDropDownState> categoryKey = new .......
final MyDropDown categoryDropdown = new MyDropDown(key: categoryKey,.....

static final GlobalKey<MyDropDownState> categoryKey = new .....
final MyDropDown categoryDropdown = new MyDropDown(key: categoryKey,......

@override
Widget build(BuildContext context) {

也就是把build方法外的varaible声明拉出来,把categoryKey设为"static"(加static是因为在initializers中只能访问static成员)

发生错误是因为您在构建方法中声明了变量“categoryKey”和“categoryDropdown”。当路由完成到 FilterPage 并且构建方法被调用从而创建 categoryKey.[=14= 的不同实例时,这会产生问题]

您在

中完成的打印也可以看到同样的情况

"print("键:“+categoryKey.toString());”

变更前:

key: [LabeledGlobalKey<MyDropDownState>#4ef43]
key: [LabeledGlobalKey<MyDropDownState>#61c88]
key: [LabeledGlobalKey<MyDropDownState>#4eb6e]

变更后:

key: [LabeledGlobalKey<MyDropDownState>#ac21e]
key: [LabeledGlobalKey<MyDropDownState>#ac21e]
key: [LabeledGlobalKey<MyDropDownState>#ac21e]

如您所见,类别键在更改后获得相同的代码。

希望对您有所帮助!