为什么Dismissible小部件在MaterialPageRoute下的工作方式不同?

时间:2019-08-17 23:23:25

标签: flutter

我正在经历Flutter的Write your first app,我想我要添加一些额外的内容。因此,我开始使用Dismissible小部件,就像在cookbook中一样。但是我注意到该小部件放在MaterialPageRoute下时的行为不同。问题在于,itemBuilder索引在我关闭该项目后不会得到更新,它将在删除之前引用旧位置。但是,从主视图中删除项目不会更新索引。有人能够解释这种行为吗?

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Startup Name Generator',
      home: RandomWords(),
    );
  }
}

class RandomWordsState extends State<RandomWords> {
  final _suggestions = generateWordPairs()
      .map((WordPair pair) => pair.asCamelCase)
      .take(10)
      .toList();
  final _biggerFont = const TextStyle(fontSize: 18.0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Startup Name Generator'),
        actions: <Widget>[
          IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }

  Widget _buildSuggestions() {
    return ListView.builder(
        padding: const EdgeInsets.all(16.0),
        itemCount: _suggestions.length,
        itemBuilder: (context, index) {
          final item = _suggestions[index];
          return Dismissible(
              key: Key(item),
              onDismissed: (direction) {
                setState(() {
                  print("MaterialApp index: $index");
                  _suggestions.remove(item);
                });
              },
              background: Container(color: Colors.red),
              child: ListTile(
                title: Text(
                  item,
                  style: _biggerFont,
                ),
              ));
        });
  }

  void _pushSaved() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        builder: (BuildContext context) {
          return Scaffold(
              appBar: AppBar(
                title: Text('Saved Suggestions'),
              ),
              body: ListView.builder(
                itemCount: _suggestions.length,
                itemBuilder: (context, index) {
                  final item = _suggestions[index];
                  return Dismissible(
                    key: Key(item),
                    onDismissed: (direction) {
                      setState(() {
                        print("MaterialPageRoute index: $index");
                        _suggestions.remove(item);
                      });
                    },
                    background: Container(color: Colors.red),
                    child: ListTile(title: Text('$item')),
                  );
                },
              ));
        },
      ),
    );
  }
}

class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => RandomWordsState();
}

从主视图开始删除项目(从顶部开始),索引反映删除。每次解雇后,顶部项的索引为0:

I/flutter ( 8176): MaterialApp index: 0
I/flutter ( 8176): MaterialApp index: 0
I/flutter ( 8176): MaterialApp index: 0

从MaterialPageRoute取消项目,从顶部开始,将保留所有项目的索引。每次解雇后,最上面的项目都有其原始索引:

I/flutter ( 8176): MaterialPageRoute index: 0
I/flutter ( 8176): MaterialPageRoute index: 1
I/flutter ( 8176): MaterialPageRoute index: 2

2 个答案:

答案 0 :(得分:0)

即使您在Route中显式调用setState(),也不会在重建项目后重新构建第二个onDismiss(),并且已从_saved中正确删除了项目。因此,内存保留原始_suggestions的原始长度和从主视图传递的项目位置。这就是为什么尽管当您关闭第一个项目(其原始索引为3)时仍会得到:


MaterialPageRoute index: 3


您可以通过将setState从其Dismissible中删除来模仿主屏幕上的相同行为。

答案 1 :(得分:0)

我的问题显然是setState not reloading state in Dart / Flutter?的重复

不同行为的原因是Route不是有状态的小部件。将其包装成StatefulWidget确实可以解决问题。