flutter - 颤动两个对象 listview.builder 向上滚动错误-返回旧的或无效的状态实例
问题描述
这些是我的项目文件:
主要.dart
import 'package:flutter/material.dart';
import 'package:flutterapp/object1form.dart';
import 'package:flutterapp/object2form.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AddScreen(),
);
}
}
class Object1 {
String name;
String count;
String units;
Object1({this.name = '', this.count = '', this.units = ''});
}
class Object2 {
int objectNumber;
String name;
Object2(int i){this.objectNumber = i; this.name = '';}
}
class AddScreen extends StatefulWidget {
@override
_AddScreenState createState() => _AddScreenState();
}
class _AddScreenState extends State<AddScreen> {
List<Object1Form> object1List = [];
List<Object2Form> object2List = [];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: new Theme(
data: new ThemeData(
primaryColorDark: Colors.blue,
),
child: ListView(children: <Widget>[
//---------------------object1-------------
SizedBox(height: 20),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 10000, minHeight: 0),
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
addAutomaticKeepAlives: true,
itemBuilder: (_, i) {
if (i == object1List.length) {
return Align(
alignment: Alignment.center,
child: RaisedButton.icon(
icon: Icon(
Icons.add,
),
textColor: Colors.white,
color: Colors.blue,
label: Text("Add object1"),
onPressed: onAddObject1,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
),
);
}
return object1List[i];
},
itemCount: object1List.length + 1,
),
),
//-----------------object2----------------------
SizedBox(height: 20),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 10000, minHeight: 0),
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
addAutomaticKeepAlives: true,
itemBuilder: (_, i) {
if (i == object2List.length) {
return Align(
alignment: Alignment.center,
child: RaisedButton.icon(
icon: Icon(
Icons.add,
),
textColor: Colors.white,
color: Colors.blue,
label: Text("Add object2"),
onPressed: (){onAddObject2(object2List.length+1);},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
),
);
}
return object2List[i];
},
itemCount: object2List.length + 1,
),
),
//--------------------------------------------------
]),
),
));
}
///on form user deleted
void onDeleteObject1(Object1 _object1) {
setState(() {
var find = object1List.firstWhere(
(it) => it.object1 == _object1,
orElse: () => null,
);
if (find != null) object1List.removeAt(object1List.indexOf(find));
});
}
///on add form
void onAddObject1() {
setState(() {
var _object1 = Object1();
object1List.add(Object1Form(
key: GlobalKey<FormState>(),
object1: _object1,
onDelete: () => onDeleteObject1(_object1),
));
});
}
///on form user deleted
void onDeleteObject2(Object2 _object2) {
setState(() {
var find = object2List.firstWhere(
(it) => it.object2 == _object2,
orElse: () => null,
);
if (find != null) object2List.removeAt(object2List.indexOf(find));
for(int j = 0; j< object2List.length; j++){
object2List[j].object2.objectNumber=j+1;
}
});
}
///on add form
void onAddObject2(int i) {
setState(() {
var _object2 = Object2(i);
object2List.add(Object2Form(
key: GlobalKey<FormState>(),
object2: _object2,
onDeleteObject2: () => onDeleteObject2(_object2),
));
});
}
}
object1form.dart:
import 'package:flutter/material.dart';
import 'package:flutterapp/main.dart';
typedef OnDelete();
class Object1Form extends StatefulWidget {
final Object1 object1;
final OnDelete onDelete;
final state = new _Object1FormState();
Object1Form({Key key, this.object1, this.onDelete}) : super(key: key);
@override
_Object1FormState createState() => state;
bool isValid() => state.validate();
}
class _Object1FormState extends State<Object1Form> {
final _formKey = GlobalKey<FormState>();
List<String> _units = <String>['', 'red', 'green', 'blue', 'orange'];
String _unit = '';
@override
Widget build(BuildContext context) {
final halfMediaWidth = MediaQuery.of(context).size.width;
return Padding(
padding: EdgeInsets.all(16),
child: Material(
elevation: 1,
clipBehavior: Clip.antiAlias,
borderRadius: new BorderRadius.circular(30.0),
color: Colors.white70,
child: new Theme(
data: new ThemeData(
primaryColorDark: Colors.blue,
),
child: Form(
key: _formKey,
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Column(children: <Widget>[
Container(
alignment: Alignment.topCenter,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: halfMediaWidth * 0.8,
child: Padding(
padding: EdgeInsets.only(
left: 16, right: 16, top: 10, bottom: 10),
child: TextFormField(
onSaved: (val) => widget.object1.name = val,
validator: (val) => val.length > 3
? null
: 'invalid',
decoration: InputDecoration(
labelText: 'Name',
hintText: 'Enter Name',
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius:
new BorderRadius.circular(30.0),
borderSide:
new BorderSide(color: Colors.blue),
),
isDense: true,
),
),
),
),
Container(
width: halfMediaWidth * 0.1,
child: IconButton(
icon: Icon(Icons.delete),
onPressed: widget.onDelete,
),
),
]),
),
]),
Column(children: <Widget>[
Container(
alignment: Alignment.topCenter,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: halfMediaWidth * 0.3,
child: Padding(
padding: EdgeInsets.only(
left: 16, right: 5, bottom: 10),
child: TextFormField(
onSaved: (val) =>
widget.object1.count = val,
validator: (input) {
final isDigitsOnly = int.tryParse(input);
return isDigitsOnly == null
? 'Input needs to be digits only'
: null;
},
decoration: InputDecoration(
labelText: 'Count',
hintText: 'Enter Count',
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius:
new BorderRadius.circular(30.0),
borderSide:
new BorderSide(color: Colors.blue),
),
),
),
)),
Container(
width: halfMediaWidth * 0.6,
child: Padding(
padding: EdgeInsets.only(left: 5, right: 2),
child: new FormField(
builder: (FormFieldState state) {
return InputDecorator(
decoration: InputDecoration(
labelText: 'Unit',
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius:
new BorderRadius.circular(30.0),
borderSide: new BorderSide(
color: Colors.blue),
),
isDense: true,
),
isEmpty: _unit == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
value: _unit,
isDense: true,
onChanged: (String newValue) {
setState(() {
widget.object1.units = newValue;
_unit = newValue;
state.didChange(newValue);
});
},
items: _units.map((String value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
}).toList(),
),
),
);
},
),
)),
],
),
),
]),
]))),
));
}
///form validator
bool validate() {
var valid = _formKey.currentState.validate();
if (valid) _formKey.currentState.save();
return valid;
}
}
object2form.dart:
import 'package:flutter/material.dart';
import 'package:flutterapp/main.dart';
typedef OnDeleteObject2();
class Object2Form extends StatefulWidget {
final Object2 object2;
final OnDeleteObject2 onDeleteObject2;
final state = new _Object2FormState();
Object2Form({Key key, this.object2, this.onDeleteObject2}) : super(key: key);
@override
_Object2FormState createState() => state;
bool isValid2() => state.validateObject2();
}
class _Object2FormState extends State<Object2Form> {
final _form2 = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
final halfMediaWidth = MediaQuery.of(context).size.width;
int objectNumber = widget.object2.objectNumber;
return Padding(
padding: EdgeInsets.all(16),
child: Material(
elevation: 1,
clipBehavior: Clip.antiAlias,
borderRadius: new BorderRadius.circular(30.0),
color: Colors.white70,
child: new Theme(
data: new ThemeData(
primaryColorDark: Colors.blue,
),
child: Form(
key: _form2,
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
Column(children: <Widget>[
Container(
alignment: Alignment.topCenter,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: halfMediaWidth * 0.8,
child: Padding(
padding: EdgeInsets.only(
left: 16, right: 16, top: 10, bottom: 10),
child: TextFormField(
onSaved: (val) => widget.object2.name = val,
validator: (val) => val.length > 3
? null
: 'invalid',
decoration: InputDecoration(
labelText: 'name',
hintText: 'Enter name',
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius:
new BorderRadius.circular(30.0),
borderSide:
new BorderSide(color: Colors.blue),
),
isDense: true,
),
keyboardType: TextInputType.multiline,
maxLines: 10,
),
),
),
Column(children: <Widget>[
Container(
width: halfMediaWidth * 0.1,
child: IconButton(
icon: Icon(Icons.delete),
onPressed: widget.onDeleteObject2,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 30,
height: 30,
child: Center(
child:
Text('$objectNumber', style:TextStyle(fontWeight: FontWeight.bold,fontSize: 20)),),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.blue,
),
)
],
),
])
]),
),
]),
]))),
));
}
///form validator
bool validateObject2() {
var valid = _form2.currentState.validate();
if (valid) _form2.currentState.save();
return valid;
}
}
我用两个动态列表构建了一个应用程序。当我将对象添加到两个列表并向上滚动时,出现此错误:
════════ 小部件库捕获的异常═════════════════════════════␕════════════ ══════════════════ 在构建 NotificationListener 时引发了以下断言:Object1Form-[LabeledGlobalKey#c1dbd] 的 createState 函数返回了旧的或无效的状态实例:Object1Form-[LabeledGlobalKey# c1dbd],不为空,违反 createState 的约定。'package:flutter/src/widgets/framework.dart':断言失败:第 4324 行 pos 7:'_state._widget == null'
断言表明框架本身存在错误,或者我们应该在此错误消息中提供更多信息,以帮助您确定和修复根本原因。无论哪种情况,请通过在 GitHub 上提交错误报告此断言: https ://github.com/flutter/flutter/issues/new?template=BUG.md
相关的导致错误的小部件是: ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 当抛出异常时,这是堆栈:
2 个新的 StatefulElement (package:flutter/src/widgets/framework.dart:4324:7)
3 StatefulWidget.createElement (package:flutter/src/widgets/framework.dart:809:38)
4 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3189:40)
5 Element.updateChild (包:flutter/src/widgets/framework.dart:2988:12)
6 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5445:14)
... ═══════════════════════════════════════␐════════␐═══ ══════════════════════════════════════════════════ ═══
════════ (2) widgets库捕获的异常════════════════════════════════ ═════════════════ 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart':断言失败:第 263 行 pos 16:'child == null || indexOf(child) > index': 不正确。相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════
════════ (3)widgets库捕获的异常════════════════════════════␕═══════════ ═════════════════ 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart':断言失败:第 263 行 pos 16:'child == null || indexOf(child) > index': 不正确。相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════
════════ (4) widgets库捕获的异常════════════════════════════␕══ ═════════════════ 'package:flutter/src/rendering/sliver_multi_box_adaptor.dart':断言失败:第 263 行 pos 16:'child == null || indexOf(child) > index': 不正确。相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════
════════ (5)渲染库捕获的异常════════════════════════════════ ═══════════════ 'package:flutter/src/widgets/framework.dart':断言失败:第 2416 行 pos 20:'_debugCurrentBuildTarget == context':不正确。相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════
════════ (6)渲染库捕获的异常════════════════════════════════ ═══════════════ getter 'scrollOffsetCorrection' 在 null 上被调用。Receiver: null 尝试调用:scrollOffsetCorrection 相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ═════════ ══════════════════════════════════════════════════ ═════════════════════════════════════════
════════ (7) 渲染库捕获的异常═════════════════════════════════ ═══════════════ 方法 'debugAssertIsValid' 在 null 上调用。Receiver: null 尝试调用:debugAssertIsValid() 相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ═══════ ══════════════════════════════════════════════════ ══════════════════════════════════════════
════════ (8) 渲染库捕获的异常═════════════════════════════════════════ ═══════════════ RenderBox 未布局:RenderShrinkWrappingViewport#6e3f7 relayoutBoundary=up15 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE 'package:flutter/src/rendering/box.dart' :断言失败:第 1687 行 pos 12:'hasSize' 相关的导致错误的小部件是:ListView file:///C:/Users/itay1/AndroidStudioProjects/flutter_app/lib/main.dart:57:33 ════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════
解决方案
改变这两个:
- _Object1FormState createState() => 状态;到 _Object1FormState createState() => _Object1FormState;
- _Object2FormState createState() => 状态;到 _Object2FormState createState() => _Object2FormState();
推荐阅读
- java - spring-data-elasticsearch 自定义日期格式错误
- firebase-authentication - 下一个js和firebase认证登录页面问题
- excel - 表示的枢轴
- json - 无法使用 getJSON 从卡片反人类 API 中获取数据
- database - 在 cmder 上使用 .bash_profile 创建 mongoDB 别名不起作用
- html - 使 div 的 50% 不是浏览器宽度
- microservices - 我可以在我的组织中拥有一个 Gitlab 管道模板吗?
- c# - C# ListView 排序方法不能正确排序数字数据
- javascript - 如何在javascript中随机排序数组?
- javascript - 如果在 ES6 中的字符串中包含,则返回 True