我在Android Studio中工作,并从Firebase检索以下数据:
coloursets:
default:
name: "Default colour set"
description: "Default set of colours"
colours:
white:
red: 255
green: 255
blue: 255
name: "white"
black:
red: 0
green: 0
blue: 0
name: "black"
我正在检索它:
public void initialiseColourSet(ValueEventListener listener) {
if(this.key == null) return;
DatabaseReference mColourSetReference = FirebaseDatabase.getInstance().getReference()
.child("coloursets").child(this.key);
mColourSetReference.addListenerForSingleValueEvent(listener);
}
其中“key”设置为“default”,“listener”为:
new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<ChartColour> colourList= new ArrayList<>();
Map<String, HashMap> objectMap = (HashMap<String, HashMap>) dataSnapshot.getValue();
// SOMETHING NEEDS TO GO HERE - SEE BELOW
}
}
ColourSet类具有以下内容:
String key, name, description;
ArrayList<ChartColour> colours = new ArrayList<>();
所以,我想循环'objectMap'来获取colourSet名称和描述,然后将颜色列表放入局部变量colourList,然后用于在ColourSet对象中设置'colors'。
我只是无法在侦听器中获得正确的循环。我查了很多答案,但似乎没有一个适用于我的情况。
目前我在听众中有以下内容:
new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<ChartColour> colourList= new ArrayList<>();
Map<String, HashMap> objectMap = (HashMap<String, HashMap>) dataSnapshot.getValue();
for (Map.Entry<String, HashMap> entry : objectMap.entrySet()) {
switch (entry.getKey()) {
case "name":
mColourSet.setName(String.valueOf(entry.getValue()));
break;
case "description":
mColourSet.setDescription(String.valueOf(entry.getValue()));
break;
case "colours":
// Need some kind of FOR LOOP here
ChartColour colour = new ChartColour();
/*
colour.setKey(??);
colour.setName(??);
colour.setRed(??);
... etc ... */
colourList.add(colour);
// END OF FOR LOOP
mColourSet.setColours(colourList);
}
}
}
});
所以,我只是不确定我需要在侦听器的FOR循环中放置什么,以便循环颜色。到目前为止我尝试的所有东西都给了我一条摇摆不定的红线,没有任何对错误的解释。
我花了一些时间来查看你的代码,我注意到了一些似乎没有的东西。
首先,当我尝试实现ValueEventListener
时,还有另一种方法需要实现。也许代码版本存在一些差异,但这可能是一个微不足道的问题。
@Override
public void onCancelled(DatabaseError error) { }
其次,dataSnapshot.getValue()
返回值的类型转换不正确。样本数据与数据为Map<String, HashMap>
的概念不匹配。 “名称”和“描述”条目显然是简单的String
s,而不是HashMap
s。我想在运行时会失败。你更有可能投射到Map<String, ?>
。从那时起,您将必须通知代码每个条目值的预期值,根据哪个键,它可以变化为String
或Map
或Integer
。如果我不得不猜测你的onDataChange
方法应该是什么样子(根据你的样本数据),它看起来像这样:
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
@SuppressWarnings("unchecked")
Map<String, ?> defaultColourSet = (Map<String, ?>)dataSnapshot.getValue();
if (defaultColourSet == null) {
/* log a warning, DataSnapshot.getValue may return null */
return;
}
List<ChartColour> colourList= new ArrayList<>();
for (Map.Entry<String, ?> colorSetEntry : defaultColourSet.entrySet()) {
switch (colorSetEntry.getKey()) {
case "name":
mColourSet.setName((String)colorSetEntry.getValue());
break;
case "description":
mColourSet.setDescription((String)colorSetEntry.getValue());
break;
case "colours":
@SuppressWarnings("unchecked")
Map<String, ?> colourMap = (HashMap<String, ?>)colorSetEntry.getValue();
for (Map.Entry<String, ?> colourEntry : colourMap.entrySet()) {
@SuppressWarnings("unchecked")
Map<String, ?> colourValueMap = (Map<String, ?>)colourEntry.getValue();
ChartColour colour = new ChartColour();
// Note that the following calls are based on assumption...
colour.setName((String)colourValueMap.get("name"));
colour.setRed((Integer)colourValueMap.get("red"));
colour.setGreen((Integer)colourValueMap.get("green"));
colour.setBlue((Integer)colourValueMap.get("blue"));
colourList.add(colour);
}
mColourSet.setColours(colourList);
break;
}
}
}
我已经在未经检查的强制转换发生的地方添加了@SupressWarnings("unchecked")
,以指示强制转换是基于编译器无法获得的知识。它严格按照JSON数据的布局进行通知。它可能在运行时失败,特别是在数据发生变化时。我建议添加更强大的错误处理,比如try-catch来处理ClassCastException
。