我尝试保存设备永久字符串列表。尝试通过弹出对话框添加列表时,显示以下错误
E / flutter(10074):[ERROR:flutter / lib / ui / ui_dart_state.cc(148)]未处理的异常:NoSuchMethodError:方法'add'在null上调用。 >
E / flutter(10074):接收方:空
E / flutter(10074):尝试调用:add(“ drinks”)
打开页面时,不会显示ListView上的其他内容。 (它会在您进入屏幕对话框后打开)
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Categories extends StatefulWidget {
@override
_CategoriesState createState() => _CategoriesState();
}
class _CategoriesState extends State<Categories> {
List<String> categoryList = List<String>();
TextEditingController _textFieldController = TextEditingController();
int count = 0;
@override
Widget build(BuildContext context) {
if (categoryList == null) {
setState(() {
categoryList = ['Food', 'Clothes'];
});
}
_update();
return Scaffold(
appBar: AppBar(
title: Text("Categories"),
),
body: SafeArea(
child: Container(
color: Colors.white,
child: getCategoriesListView(),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
_displayDialog(context);
});
},
),
);
}
ListView getCategoriesListView() {
return ListView.builder(
itemCount: categoryList.length,
itemBuilder: (context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
title: Text(categoryList[position]),
trailing: GestureDetector(
child: Icon(
Icons.delete,
color: Colors.grey,
),
onTap: () {
setState(() {
_delete(context, categoryList[position]);
});
},
),
),
);
});
}
void _add(BuildContext context, String category) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
categoryList.add(category);
prefs.setStringList('Categories', categoryList);
showSnackBar(context, 'Your category was added');
}
void _delete(BuildContext context, String category) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
categoryList.remove(category);
prefs.setStringList('Categories', categoryList);
showSnackBar(context, 'Your category was removed');
}
void _update() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
categoryList = prefs.getStringList('Categories');
}
void showSnackBar(BuildContext context, String message) async {
final snackBar = SnackBar(content: Text(message));
Scaffold.of(context).showSnackBar((snackBar));
}
_displayDialog(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Add new category'),
content: TextField(
controller: _textFieldController,
),
actions: <Widget>[
FlatButton(
child: Text('ADD'),
onPressed: () {
setState(() {
String name = _textFieldController.text;
print(name);
_add(context, name);
Navigator.of(context).pop();
});
},
),
FlatButton(
child: Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
}
答案 0 :(得分:0)
您应该在_update()
函数而不是initState()
中调用build()
方法。现在,每次您调用setState()
时,都会调用build()
函数,而该函数又会依次调用update()
,由于categoryList
被覆盖。
因此,您无法向List
添加新项目。
您可以执行以下操作-
@override
void initState() {
super.initState();
_update();
}
然后不要在_update()
内调用build()
方法。
但是现在,由于我们将_update()
调用移到了build()
之外,您将不得不在setState()
内使用_update()
以便正确刷新状态。
void _update() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
categoryList = prefs.getStringList('Categories');
}
希望这会有所帮助!
此外,您不应该在setState()
方法内直接调用build()
,否则可能会出错,因此也可以将以下代码移到initState()
内。
//Move this inside initState();
if (categoryList == null) {
setState(() {
categoryList = ['Food', 'Clothes'];
});
}
在调用initState()
方法之前初始化小部件时,build()
方法仅被调用一次。