2017-10-14 50 views
1

我Android Studio中工作,并检索从火力地堡以下数据:如何在检索Firebase数据后循环访问HashMap?

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); 

}

,其中 “关键” 是设置为“默认”,“听众”是:

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类ha S中的以下内容:

String key, name, description; 
ArrayList<ChartColour> colours = new ArrayList<>(); 

所以,我要循环“ObjectMap的”,让colourSet名称和描述,然后得到的颜色列表到本地变量colourList,然后将其用于设置“颜色'在ColourSet对象中。

我只是无法在侦听器中获得正确的循环。我查了很多答案,但没有一个似乎适用于我的案例。

目前我已在听众中的以下内容:

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循环的监听器,以循环在颜色。我到目前为止所尝试的所有东西都只是给了我一个闪烁的红线,而没有任何解释什么是错的。

任何人都可以告诉我吗?感谢您提供任何帮助。

+1

我不确定你的红色曲线在哪里,但你的'HashMap'作为外部映射的值类型没有设置泛型类型,这意味着键和值都解析为'Object' 。 – Dave

+0

谢谢。你的意思是objectMap吗?他们应该设置什么? – Sharon

+1

我的意思是在'Map '中,'HashMap'部分没有指定类型参数,所以它实际上是'HashMap '。我想在这种情况下它需要是'HashMap '。这可能很容易导致代码中的一些扭曲的红线,但不知道错误的位置,我无法确定。我还没有试图运行你的代码呢... – Dave

回答

1

我花了一点时间来看看你的代码,并且我注意到一些看起来没有的东西。

首先,当我尝试实施ValueEventListener时,还有另一种方法需要实施。也许代码版本有一些区别,但这可能是一个微不足道的问题。

@Override 
public void onCancelled(DatabaseError error) { } 

其次,你的类型转换为dataSnapshot.getValue()的返回值可以是不正确的。样本数据与数据为Map<String, HashMap>的概念不匹配。 “名称”和“描述”条目显然是简单的,而不是HashMap s。我会想象在运行时失败。这很可能是你应该铸造到Map<String, ?>。从这一点,你必须告知代码什么是预期的每个输入值,根据哪个密钥,可变的是StringMapInteger。如果我不得不冒险在你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

+0

谢谢!是的,我有OnCancelled,只是没有把它放在这里,以节省空间 - 道歉,我应该明确表示。 – Sharon

+0

我会检查其余的,看看我如何继续。非常感谢你的帮助。 – Sharon

+0

谢谢!这使事情变得更清晰。我没有意识到我可以放一个?在Map定义中 - 我试图使用HashMap,然后将其转换为我所需要的,这显然不起作用。我现在将处理错误处理 - 只是想让事情先行。再次感谢你的帮助! – Sharon