我的应用程序上有一个“个人资料”标签。我称Future为将配置文件存储在sqflite数据库中,并将其存储在列表中并在卡中显示所有内容。
class ProfilePage extends StatefulWidget {
@override
_ProfilePageState createState() => new _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
TabController tabController;
List<Patient> listOfPatients = List<Patient>();
List<int> primaryKeys = List<int>();
int profileCount = 0;
final dbHelper = DatabaseHelper.instance;
....
@override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildProfileTab(),
...........
);
}
Widget _buildProfileTab() {
return FutureBuilder<dynamic>(
future: _getAllProfiles(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
case ConnectionState.done:
return _createProfileCards();
}
return null; // unreachable
},
);
}
Future _getAllProfiles() async {
listOfPatients.clear();
primaryKeys.clear();
await dbHelper.queryAllRows().then((allRows) {
allRows.forEach((row) {
//do some editing with the row and place the "temp" patient object in the list of patients list, and get it's id
listOfPatients.add(temp);
primaryKeys.add(row['_id']);
});
});
}
Widget _createProfileCards() {
return ListView.builder(
itemCount: listOfPatients.length,
itemBuilder: (context, position) {
return GestureDetector(
onLongPress: () {
...........
...........
},
child: Container(
padding: position == listOfPatients.length - 1
? EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 80.0)
: EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
child: Card(
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: ListTile(
contentPadding: EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
leading: listOfPatients[position].gender == 0
? CircleAvatar(
radius: 25.0,
backgroundColor: Colors.grey,
child: Icon(
MdiIcons.humanMale,
color: Colors.white,
),
)
: CircleAvatar(
radius: 25.0,
backgroundColor: Colors.grey,
child: Icon(MdiIcons.humanFemale, color: Colors.white),
),
title: Text(
listOfPatients[position].name,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
),
subtitle: Text(listOfPatients[position].getAge() +
"\n" +
displayGenderString(listOfPatients[position].gender)),
isThreeLine: true,
trailing: IconButton(
icon: Text(
"VIEW",
style: TextStyle(
color: Color(0xFF2A8E5C),
fontWeight: FontWeight.bold,
),
),
onPressed: () {
if (listOfPatients.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PatientPage(
listOfPatients[position], primaryKeys[position]), // this is where the error occurs when textfield is tapped
),
);
}
},
),
),
),
),
);
},
);
}
一切正常。然后,当您点击个人资料卡中的“查看”图标按钮时,它会转到另一个有状态的小部件(PatientPage)-进入个人资料卡的更详细版本,并且它将对象患者传递给PatientPage使用。
在PatientPage中,我有一个ListTile,当用户想要使用一元运算符编辑“注释”部分时,我将其更改为文本字段。
Text(
"Notes",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
isNotesEditing
? Column(
children: <Widget>[
TextField(
controller: notesEditController,
),
ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
child: Text("SAVE"),
onPressed: () {
//update DB
widget.patientInfo.notes =
notesEditController.text;
setState(() {
isNotesEditing = false;
});
},
),
FlatButton(
child: Text("CANCEL"),
onPressed: () {
setState(() {
isNotesEditing = false;
});
},
)
],
)
],
)
: ListTile(
isThreeLine: true,
subtitle: Text(""),
trailing: IconButton(
icon: Icon(Icons.edit),
onPressed: () {
setState(() {
isNotesEditing = true;
});
},
),
title: widget.patientInfo.notes == ""
? Text("None")
: (widget.patientInfo.notes),
),
我的问题是,当我点击文本字段时,ProfilePage(父窗口小部件)窗口小部件会重新生成(根据我使用断点的调查结果)。并产生错误“ RangeError(索引):无效值:有效值范围为空:0”。我不知道为什么它会像这样重建并且将listOfPatients留空。我什至在卡的onPressed回调中添加了检查功能,仅在列表不为空时才分配功能。
if (listOfPatients.isNotEmpty) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PatientPage(
listOfPatients[position], primaryKeys[position]), // this is the part where flutter points out the invalid range
),
);
}
感谢您的帮助。谢谢!