【问题标题】:How to fix error Concurrent modification during iteration: Instance(length:0) of '_GrowableList'如何修复错误迭代期间的并发修改:'_GrowableList'的实例(长度:0)
【发布时间】:2021-03-20 06:17:36
【问题描述】:

我正在尝试创建一个小卡片“游戏”,现在我尝试在用户点击可用按钮时简单地重置我的卡片列表。

点击“Reiniciar”按钮时,我收到以下错误消息。我试图通过声明_cardsAux=_cards 重新初始化,但它什么也没做......所以我尝试了_cardsAux.addAll(_cards),它返回错误。我知道如果我将我的卡片列表硬编码到 cardAux 变量中,它可以工作,但我不希望那样......我可以做些什么来解决这个问题并达到重置卡片列表的预期结果,以便用户可以保留玩吗?

> ======== Exception caught by gesture =============================================================== The following ConcurrentModificationError was thrown while handling a
> gesture: Concurrent modification during iteration: Instance(length:0)
> of '_GrowableList'.
> 
> When the exception was thrown, this was the stack: 
> #0      List.addAll (dart:core-patch/growable_array.dart:215:11)
> #1      _MyHomePageState._getACard.<anonymous closure> (package:our_cards/main.dart:102:29)
> #2      State.setState (package:flutter/src/widgets/framework.dart:1269:30)
> #3      _MyHomePageState._getACard (package:our_cards/main.dart:96:5)
> #4      _MyHomePageState.build.<anonymous closure> (package:our_cards/main.dart:163:36) ... Handler: "onTap" Recognizer:
> TapGestureRecognizer#3ba91   debugOwner: GestureDetector   state:
> possible   won arena   finalPosition: Offset(218.7, 456.4)  
> finalLocalPosition: Offset(60.4, 25.6)   button: 1   sent tap down

我的 main.dart 代码

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

int  random(min, max){
  var rn = new Random();
  return min + rn.nextInt(max - min);
}
final _cards = [
  {'card':'Card A'},
  {'card':'Card B'},
  {'card':'Card C'}
];
var _card ='Press arrow Icon below to Start';


void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Our Cards',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Our Cards'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;


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

class _MyHomePageState extends State<MyHomePage> {

  int pop;
  var _cardsAux = _cards ;

  void _getACard(bool isReset) {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      if(isReset){_cardsAux.addAll(_cards);}
      if(_cardsAux.length== 0){
        _card = 'No More Cards';
      }
      else {
        pop = random(0, _cardsAux.length);
        _card = _cardsAux[pop]['card'];
        _cardsAux.removeAt(pop);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
                padding: EdgeInsets.all(30),
                child:
                  Text('$_card',
                        style: Theme.of(context).textTheme.headline3,
                  )
            ),
            Container(
              padding: EdgeInsets.all(30),
                child: FlatButton(
                  color: Colors.blue,
                  textColor: Colors.white,
                  padding: EdgeInsets.all(8.0),
                  splashColor: Colors.blueAccent,
                  onPressed: () => _getACard(true),
                  child: Text(
                    "Reiniciar",
                    style: TextStyle(fontSize: 20.0),
                  ),
                ),
            ),

          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () =>_getACard(false),
        tooltip: 'Next Card',
        child: Icon(Icons.arrow_forward),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

【问题讨论】:

  • 我换了行>> _cardsAux.addAll(_cards); > _cardsAux = _cards;

标签: flutter dart


【解决方案1】:

您可以在下面复制粘贴运行完整代码
在您的代码中,_cardsAux_cards
您可以在initState 拨打_cardsAux = List.from(_cards);
代码sn-p

List<Map<String, String>> _cardsAux;

@override
  void initState() {
    _cardsAux = List.from(_cards);

工作演示

完整代码

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

int random(min, max) {
  var rn = new Random();
  return min + rn.nextInt(max - min);
}

final List<Map<String, String>> _cards = [
  {'card': 'Card A'},
  {'card': 'Card B'},
  {'card': 'Card C'}
];
var _card = 'Press arrow Icon below to Start';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Our Cards',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Our Cards'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int pop;
  List<Map<String, String>> _cardsAux;

  @override
  void initState() {
    _cardsAux = List.from(_cards);
    super.initState();
  }

  void _getACard(bool isReset) {
    setState(() {
      if (isReset) {
        _cardsAux.addAll(_cards);
      }
      if (_cardsAux.length == 0) {
        _card = 'No More Cards';
      } else {
        pop = random(0, _cardsAux.length);
        _card = _cardsAux[pop]['card'];
        print(_card);
        print("_cards ${_cards.length}");
        print("_cardsAux ${_cardsAux.length}");
        _cardsAux.removeAt(pop);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Container(
                padding: EdgeInsets.all(30),
                child: Text(
                  '$_card',
                  style: Theme.of(context).textTheme.headline3,
                )),
            Container(
              padding: EdgeInsets.all(30),
              child: FlatButton(
                color: Colors.blue,
                textColor: Colors.white,
                padding: EdgeInsets.all(8.0),
                splashColor: Colors.blueAccent,
                onPressed: () => _getACard(true),
                child: Text(
                  "Reiniciar",
                  style: TextStyle(fontSize: 20.0),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _getACard(false),
        tooltip: 'Next Card',
        child: Icon(Icons.arrow_forward),
      ),
    );
  }
}

【讨论】:

  • 非常感谢。为什么要有 initState 方法?我尝试使用 `List> _cardsAux = List.from(_cards);` 它也有效
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 2020-04-21
  • 2014-04-20
  • 2021-04-04
  • 1970-01-01
  • 2014-09-04
  • 2020-10-30
  • 2020-05-08
相关资源
最近更新 更多