Android 颤振火基-下拉菜单项:方法';地图';被调用为空
在我的应用程序中,我想根据动物的种类(如果是狗或猫)展示疫苗。我遇到一个错误:对null调用了方法“map”。尝试呼叫:地图下拉菜单项。为什么会这样?我已经在方法中添加了async和await,我不明白为什么它仍然为null。下面是我的代码: 1) 在这里,我在init中调用我的DropdownContent类来准备小部件内行中的DropdownMenuItemAndroid 颤振火基-下拉菜单项:方法';地图';被调用为空,android,ios,firebase,flutter,dart,Android,Ios,Firebase,Flutter,Dart,在我的应用程序中,我想根据动物的种类(如果是狗或猫)展示疫苗。我遇到一个错误:对null调用了方法“map”。尝试呼叫:地图下拉菜单项。为什么会这样?我已经在方法中添加了async和await,我不明白为什么它仍然为null。下面是我的代码: 1) 在这里,我在init中调用我的DropdownContent类来准备小部件内行中的DropdownMenuItem class _VaccineDetailFormState extends State<VaccineDetailForm>
class _VaccineDetailFormState extends State<VaccineDetailForm> {
final DataRepository repository = DataRepository();
String selectedVaccine = "Select";
List<String> vaccinesBySpecie;
initState() {
DropdownContent.getVaccines(widget.selectedPetID).then((value) => vaccinesBySpecie = value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
[...]
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new DropdownButton<String>(
value: widget.vaccine.name == null ? selectedVaccine: widget.vaccine.name,
underline: Container(
height: 2,
color: Colors.grey,
),
onChanged: (String newValue) {
setState(() {
selectedVaccine = newValue;
widget.vaccine.name = newValue;
});
},
items: vaccinesBySpecie.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
]),
[...]
Container(
child: FutureBuilder <List<String>>(
future: DropdownContent.getVaccines(widget.selectedPetID),
builder: (context, AsyncSnapshot snapshot) {
if(snapshot.data == null) {
return CircularProgressIndicator();
}
else {
return DropdownButton<String>(
value: widget.vaccine.name == null? selectedVaccine: widget.vaccine.name,
underline: Container(
height: 2,
color: Colors.grey,
),
onChanged: (String newValue) {
setState(() {
selectedVaccine = newValue;
widget.vaccine.name = newValue;
});
},
items: snapshot.data.map<DropdownMenuItem<String>>((value) =>
new DropdownMenuItem<String>(
child: Text(value),
value: value,
))
.toList(),
);
}
})
)
class\u VaccineDetailFormState扩展状态{
最终数据存储库=数据存储库();
String selectedVaccine=“选择”;
列出疫苗种类;
initState(){
getVaccines(widget.selectedPetID)。然后((value)=>vaccinesBySpecie=value);
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
[...]
新行(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
新下拉按钮(
值:widget.vaccine.name==null?selectedVaccine:widget.vaccine.name,
下划线:容器(
身高:2,
颜色:颜色。灰色,
),
onChanged:(字符串newValue){
设置状态(){
selectedVaccine=newValue;
widget.vaccine.name=newValue;
});
},
项目:疫苗种类图((字符串值){
返回下拉菜单项(
价值:价值,
子项:文本(值),
);
}).toList(),
)
]),
[...]
2) 下面是DropdownContent类,它在getVaccines()方法中搜索存储库以找出当前动物的物种,然后返回相应的疫苗列表
class Dropdown content
static Future<List<String>> getVaccines(String petId) async {
final DataRepository repository = DataRepository();
String currentSpecie = await repository.getSpecie(petId);
if (currentSpecie.contains('Dog')) {
return listOfVaccinesForDogs();
}
if (currentSpecie.contains('Cat')) {
return listOfVaccinesForCats();
}
}
类下拉列表内容
静态(字符串petId)异步{
最终数据存储库=数据存储库();
字符串currentSpecie=await repository.getSpecie(petId);
如果(当前种类包含('Dog')){
返回疫苗列表fordogs();
}
if(当前规格包含('Cat')){
疫苗接种者返回列表();
}
}
3) 最后是搜索动物物种的repository类
class Repository
Future<String> getSpecie(String petId) async {
DocumentReference documentReference = petCollection.document(petId);
await documentReference.get().then((snapshot) {
return snapshot.data['specie'].toString();
});
}
Future<String> getSpecie(String petId) async {
DocumentReference documentReference = petCollection.document(petId);
String specie;
await documentReference.get().then((snapshot) {
specie = snapshot.data['specie'].toString();
});
return specie;
}
类存储库
未来的getSpecie(字符串petId)异步{
DocumentReference=petCollection.document(petId);
等待documentReference.get()。然后((快照){
返回snapshot.data['specie'].toString();
});
}
虽然initState方法可能是异步的,但构建方法不是。因此在调用构建方法时,vaccinesBySpecie方法为空。
解决此问题的最佳方法是初始化您的列表vaccinesBySpecie
,就像这样列表vaccinesBySpecie=[];
。这样,当调用构建方法时,它不会为null
作为旁注,我建议如果可以的话,使用FutureBuilder或StreamBuilder,这样你可以处理没有值(即它为空)和有值(即它不是空)的情况。迪恩说的话启发了我的想法。我通过得出以下答案解决了这个问题: 1) 小部件内的DropdownMenuItem
class _VaccineDetailFormState extends State<VaccineDetailForm> {
final DataRepository repository = DataRepository();
String selectedVaccine = "Select";
List<String> vaccinesBySpecie;
initState() {
DropdownContent.getVaccines(widget.selectedPetID).then((value) => vaccinesBySpecie = value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
[...]
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new DropdownButton<String>(
value: widget.vaccine.name == null ? selectedVaccine: widget.vaccine.name,
underline: Container(
height: 2,
color: Colors.grey,
),
onChanged: (String newValue) {
setState(() {
selectedVaccine = newValue;
widget.vaccine.name = newValue;
});
},
items: vaccinesBySpecie.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
)
]),
[...]
Container(
child: FutureBuilder <List<String>>(
future: DropdownContent.getVaccines(widget.selectedPetID),
builder: (context, AsyncSnapshot snapshot) {
if(snapshot.data == null) {
return CircularProgressIndicator();
}
else {
return DropdownButton<String>(
value: widget.vaccine.name == null? selectedVaccine: widget.vaccine.name,
underline: Container(
height: 2,
color: Colors.grey,
),
onChanged: (String newValue) {
setState(() {
selectedVaccine = newValue;
widget.vaccine.name = newValue;
});
},
items: snapshot.data.map<DropdownMenuItem<String>>((value) =>
new DropdownMenuItem<String>(
child: Text(value),
value: value,
))
.toList(),
);
}
})
)
容器(
孩子:未来建设者(
未来:DropdownContent.getVaccines(widget.selectedPetID),
生成器:(上下文,异步快照){
如果(snapshot.data==null){
返回循环ProgressIndicator();
}
否则{
返回下拉按钮(
值:widget.vaccine.name==null?selectedVaccine:widget.vaccine.name,
下划线:容器(
身高:2,
颜色:颜色。灰色,
),
onChanged:(字符串newValue){
设置状态(){
selectedVaccine=newValue;
widget.vaccine.name=newValue;
});
},
项目:snapshot.data.map((值)=>
新下拉菜单项(
子项:文本(值),
价值:价值,
))
.toList(),
);
}
})
)
2) DropdownContent类,搜索存储库以查找当前动物的物种,然后返回相应的疫苗列表:
static Future<List<String>> getVaccines(String petId) async {
final DataRepository repository = DataRepository();
String currentSpecie;
await repository.getSpecie(petId).then((value) {
currentSpecie = value;
});
if (currentSpecie.contains('Dog')) {
return listOfVaccinesForDogs();
}
if (currentSpecie.contains('Cat')) {
return listOfVaccinesForCats();
}
}
静态(字符串petId)异步{
最终数据存储库=数据存储库();
弦电流型;
等待repository.getSpecie(petId).then((值){
当前种类=值;
});
如果(当前种类包含('Dog')){
返回疫苗列表fordogs();
}
if(当前规格包含('Cat')){
疫苗接种者返回列表();
}
}
3) 搜索动物物种的存储库类
class Repository
Future<String> getSpecie(String petId) async {
DocumentReference documentReference = petCollection.document(petId);
await documentReference.get().then((snapshot) {
return snapshot.data['specie'].toString();
});
}
Future<String> getSpecie(String petId) async {
DocumentReference documentReference = petCollection.document(petId);
String specie;
await documentReference.get().then((snapshot) {
specie = snapshot.data['specie'].toString();
});
return specie;
}
Future-getSpecie(String-petId)异步{
DocumentReference=petCollection.document(petId);
弦类;
等待documentReference.get()。然后((快照){
specie=snapshot.data['specie'].toString();
});
返回物种;
}
您好。我按照您的建议进行了初始化。错误“map was called on null”已消失,但下拉列表为空,我认为这是因为您所说的FutureBuilder,所以我尝试添加此项,但现在又返回到相同的错误。