【问题标题】:How to extract a list of objects from Firebase DataSnapshot on android如何从 Android 上的 Firebase DataSnapshot 中提取对象列表
【发布时间】:2015-12-29 10:43:12
【问题描述】:

我想将所有 Firebase DataSnapshot 子级转换为 android 中的列表。

类似这样的:

mFirebaseRef = new Firebase(FIREBASE_URL);

mFirebaseRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        List<String> td = (ArrayList<String>) dataSnapshot.getValue();
        //notifyDataSetChanged();
    }

    @Override
    public void onCancelled(FirebaseError firebaseError) {

    }
});

【问题讨论】:

标签: android firebase firebase-realtime-database


【解决方案1】:

Firebase 以这种格式存储一系列值:

"-K-Y_Rhyxy9kfzIWw7Jq": "Value 1"
"-K-Y_RqDV_zbNLPJYnOA": "Value 2"
"-K-Y_SBoKvx6gAabUPDK": "Value 3"

如果这就是你拥有它们的方式,那么你得到了错误的类型。上述结构表示为Map,而不是List:

mFirebaseRef = new Firebase(FIREBASE_URL);

mFirebaseRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();

        List<Object> values = td.values();

        //notifyDataSetChanged();
    }

    @Override
    public void onCancelled(FirebaseError firebaseError) {

    }
});

【讨论】:

  • 我想要“-K-Y_Rhyxy9kfzIWw7Jq”的父列表:“值 1”“-K-Y_RqDV_zbNLPJYnOA”:“值 2”“-K-Y_SBoKvx6gAabUPDK”:“值 3”
  • 可以Map&lt;String, MyDataObject&gt; = (HashMap&lt;String, MyDataObject&gt;) dataSnapshot.getValue(); 还是必须将Object 转换为MyDataObject?
  • @Frank,Android Studio 在这一行显示红色下划线 List values =td.values();...错误:- 无法将集合对象转换为列表对象..在堆栈跟踪中抛出错误..
  • @Frank 谢谢,List&lt;Object&gt; values = td.values(); 很高兴知道。
  • @NarendraBaratam 我有同样的问题。改用这种方式:List&lt;Object&gt; values = new Arraylist&lt;&gt;(td.values());
【解决方案2】:

我希望下面的代码有效

Firebase ref = new Firebase(FIREBASE_URL);

  ref.addValueEventListener(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot snapshot) {
          Log.e("Count " ,""+snapshot.getChildrenCount());
          for (DataSnapshot postSnapshot: snapshot.getChildren()) {
            <YourClass> post = postSnapshot.getValue(<YourClass>.class);
            Log.e("Get Data", post.<YourMethod>());
          }
      }
      @Override
      public void onCancelled(FirebaseError firebaseError) {
          Log.e("The read failed: " ,firebaseError.getMessage());
      }
  });

【讨论】:

  • 当我打印日志时它为空。你能帮帮我吗?
  • 如果您只需要该数据一次,请不要忘记使用addListenerForSingleValueEvent() 而不是addValueEventListener()。
【解决方案3】:

将数据保存和检索到 - 从 Firebase (不推荐使用 2.4.2 版)

Firebase fb_parent = new Firebase("YOUR-FIREBASE-URL/");
Firebase fb_to_read = fb_parent.child("students/names");
Firebase fb_put_child = fb_to_read.push(); // REMEMBER THIS FOR PUSH METHOD

//INSERT DATA TO STUDENT - NAMES  I Use Push Method
fb_put_child.setValue("Zacharia"); //OR fb_put_child.setValue(YOUR MODEL) 
fb_put_child.setValue("Joseph"); //OR fb_put_child.setValue(YOUR MODEL) 
fb_put_child.setValue("bla blaaa"); //OR fb_put_child.setValue(YOUR MODEL) 

//GET DATA FROM FIREBASE INTO ARRAYLIST
fb_to_read.addValuesEventListener....{
    public void onDataChange(DataSnapshot result){
        List<String> lst = new ArrayList<String>(); // Result will be holded Here
        for(DataSnapshot dsp : result.getChildren()){
            lst.add(String.valueOf(dsp.getKey())); //add result into array list
        }
        //NOW YOU HAVE ARRAYLIST WHICH HOLD RESULTS




for(String data:lst){ 
         Toast.make(context,data,Toast.LONG_LENGTH).show; 
       }
    }
}

【讨论】:

    【解决方案4】:

    我做了这样的事情:

    Firebase ref = new Firebase(FIREBASE_URL);
    ref.addValueEventListener(new ValueEventListener() {
    
    @Override
    public void onDataChange(DataSnapshot snapshot) {
        Map<String, Object> objectMap = (HashMap<String, Object>)    
                 dataSnapshot.getValue();
        List<Match> = new ArrayList<Match>();
        for (Object obj : objectMap.values()) {
            if (obj instanceof Map) {
                Map<String, Object> mapObj = (Map<String, Object>) obj;
                Match match = new Match();
                match.setSport((String) mapObj.get(Constants.SPORT));
                match.setPlayingWith((String) mapObj.get(Constants.PLAYER));
                list.add(match);
            }
        }
      }
      @Override
      public void onCancelled(FirebaseError firebaseError) {
    
      }
    });
    

    【讨论】:

    • 我理解对了吗?即使您只添加一个匹配类型值,您每次都在循环?
    【解决方案5】:
    FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
     DatabaseReference databaseReference =    mFirebaseDatabase.getReference(FIREBASE_URL);
            databaseReference.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
    
                    for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
                        Log.v(TAG,""+ childDataSnapshot.getKey()); //displays the key for the node
                        Log.v(TAG,""+ childDataSnapshot.child(--ENTER THE KEY NAME eg. firstname or email etc.--).getValue());   //gives the value for given keyname
                    }
                }
            @Override
            public void onCancelled(DatabaseError databaseError) {
    
            }
        });
    

    希望对你有帮助!

    【讨论】:

      【解决方案6】:

      在我的情况下,只有给定的解决方案可以正常工作。

      Firebase ArrayList 结构的屏幕截图:

      如何从 DataSnapshot 的 Firebase 获取整个列表。

      GenericTypeIndicator<Map<String, List<Education>>> genericTypeIndicator = new GenericTypeIndicator<Map<String, List<Education>>>() {};
      Map<String, List<Education>> hashMap = dataSnapshot.getValue(genericTypeIndicator);
      
      for (Map.Entry<String,List<Education>> entry : hashMap.entrySet()) {
            List<Education> educations = entry.getValue();
              for (Education education: educations){
                   Log.i(TAG, education.Degree);
               }
      }
      

      Education.java:(模型类)。

      public class Education implements Serializable{
      
          public String Degree;
          public String Result;
      }
      

      希望这会正常工作。

      【讨论】:

        【解决方案7】:

        正如弗兰克所说,Firebase 以"key": "Value" 的格式存储值序列 这是一个地图结构

        要从此序列中获取 List,您必须

        1. 使用 String 的 HashMap 和您的 Object 初始化 GenericTypeIndicator。
        2. 将 DataSnapShot 的值作为 GenericTypeIndicator 获取到 Map。
        3. 用 HashMap 值初始化 ArrayList。

        GenericTypeIndicator<HashMap<String, Object>> objectsGTypeInd = new GenericTypeIndicator<HashMap<String, Object>>() {};
        Map<String, Object> objectHashMap = dataSnapShot.getValue(objectsGTypeInd);
        ArrayList<Object> objectArrayList = new ArrayList<Object>(objectHashMap.values());
        

        对我来说很好,希望对你有帮助。

        【讨论】:

        【解决方案8】:
        mDatabase.child("token").addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                      for (DataSnapshot snapshot:dataSnapshot.getChildren())
                      {
                         String key= snapshot.getKey();
                         String value=snapshot.getValue().toString();
                      }
                    }
        
                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        Toast.makeText(ListUser.this,databaseError.toString(),Toast.LENGTH_SHORT).show();
                    }
                });
        

        只有在孩子没有SubChild时才有效

        【讨论】:

          【解决方案9】:

          你需要编写一个自定义的 Deserializer,然后循环它并获取 hasmap 的值。

          自定义反序列化器:-

          public class UserDetailsDeserializer implements JsonDeserializer<AllUserDetailsKeyModel> {
            /*
              bebebejunskjd:{
                "email": "akhilbv1@gmail.com",
                    "mobileNum": "12345678",
                    "password": "1234567",
                    "username": "akhil"}*/
            @Override public AllUserDetailsKeyModel deserialize(JsonElement json, Type typeOfT,
                JsonDeserializationContext context) throws JsonParseException {
          
              final JsonObject jsonObject = json.getAsJsonObject();
          
              Gson gson = new Gson();
          
              Type AllUserDetailsResponseModel =
                  new TypeToken<HashMap<String, AllUserDetailsResponseModel>>(){}.getType();
          
              HashMap<String, AllUserDetailsResponseModel> user =
                  gson.fromJson(jsonObject, AllUserDetailsResponseModel);
              AllUserDetailsKeyModel result = new AllUserDetailsKeyModel();
              result.setResult(user);
              return result;
            }
          
          
          }
          

          cmets 中的代码是我的对象模型,你应该用你的模型类替换AllUserDetailsKeyModel 并将其添加到其余客户端,如下所示:-

          private Converter.Factory createGsonConverter() {
              GsonBuilder gsonBuilder = new GsonBuilder();
              gsonBuilder.registerTypeAdapter(AllUserDetailsKeyModel.class, new UserDetailsDeserializer());
              Gson gson = gsonBuilder.create();
              return GsonConverterFactory.create(gson);
            }
          

          这是用于改造的自定义转换器。

          在您的 onResponse 中,您只需循环使用 hasmaps 并按键获取值,我的模型类如下所示:-

          public class AllUserDetailsKeyModel {
          
            private Map<String, AllUserDetailsResponseModel> result;
          
            public Map<String, AllUserDetailsResponseModel> getResult() {
              return result;
            }
          
            public void setResult(Map<String, AllUserDetailsResponseModel> result) {
              this.result = result;
            }
          
          }
          

          您可能需要提供一个 T 类型,其中 T 是您的数据类型,而我的模型仅包含一个哈希图和 getter 和 setter。

          最后将自定义转换器设置为改造如下:- .addConverterFactory(createGsonConverter())

          如果您需要更多说明,请告诉我。

          【讨论】:

            【解决方案10】:

            使用 GenericTypeIndicator 从 Firebase ArrayList 结构化数据库中获取子节点列表

               //Start of Code
               Firebase ref = new Firebase(FIREBASE_URL);
               ref.addValueEventListener(new ValueEventListener(){
                  @Override
                  public void onDataChange(DataSnapshot snapshot){
                     GenericTypeIndicator<List<YourClassName>> t = new GenericTypeIndicator<List<YourClassName>>{};
                     List<YourClassName> messages = snapshot.getValue(t);
                     Log.d("Get Data Size", messages.size());
                      }
                  }
                  @Override
                  public void onCancelled(FirebaseError firebaseError){
                      Log.e("The read failed: ",firebaseError.getMessage());
                  }
               });
            

            【讨论】:

              【解决方案11】:

              像魅力一样工作

              final DatabaseReference senderDb = FirebaseDatabase.getInstance().getReference(Constant.NODE_MESSAGE).child(myId + "_" + otherId);
              
                  senderDb.addValueEventListener(new ValueEventListener() {
                      @Override
                      public void onDataChange(DataSnapshot dataSnapshot) {
                          Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
              
                          for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
                              DatabaseReference objRef = senderDb.child( childDataSnapshot.getKey());
                              Map<String,Object> taskMap = new HashMap<String,Object>();
                              taskMap.put("is_read", "1");
                              objRef.updateChildren(taskMap); //should I use setValue()...?
                              Log.v("Testing",""+ childDataSnapshot.getKey()); //displays the key for the node
                          }
              
                          //notifyDataSetChanged();
                      }
              
                      @Override
                      public void onCancelled(DatabaseError databaseError) {
              
                      }
              
                  });
              

              【讨论】:

                【解决方案12】:

                你的问题是为什么你的代码不起作用。

                这是你的代码:

                Firebase ref = new Firebase(FIREBASE_URL);
                
                  ref.addValueEventListener(new ValueEventListener() {
                      @Override
                      public void onDataChange(DataSnapshot snapshot) {
                          Log.e("Count " ,""+snapshot.getChildrenCount());
                          for (DataSnapshot postSnapshot: snapshot.getChildren()) {
                            <YourClass> post = postSnapshot.getValue(<YourClass>.class);
                            Log.e("Get Data", post.<YourMethod>());
                          }
                      }
                      @Override
                      public void onCancelled(FirebaseError firebaseError) {
                          Log.e("The read failed: " ,firebaseError.getMessage());
                      }
                  })
                

                你错过了最简单的事情:getChildren()

                FirebaseDatabase db = FirebaseDatabase.getInstance();
                DatabaseReference reference = FirebaseAuth.getInstance().getReference("Donald Trump");
                
                reference.addValueEventListener(new ValueEventListener() {
                   @Override
                   public void onDataChange(DataSnapshot dataSnapshot) {
                
                            int count = (int) dataSnapshot.getChildrenCount(); // retrieve number of childrens under Donald Trump
                
                            String[] hairColors = new String[count];
                
                            index = 0;
                            for (DataSnapshot datas : dataSnapshot.getChildren()){
                
                                hairColors[index] = datas.getValue(String.class);
                
                            }
                            index ++
                
                            for (int i = 0; i < count; i++)
                            Toast(MainActivity.this, "hairColors : " + hairColors[i], toast.LENGTH_SHORT).show();
                
                            }
                
                    }
                
                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                
                        }
                
                    });
                

                【讨论】:

                • 索引++;必须在 for (DataSnapshot datas : dataSnapshot.getChildren()){
                【解决方案13】:
                ArrayList<String> keyList = new ArrayList<String>();
                mKeyRef.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
                                String temp = childDataSnapshot.getKey();
                                keyList.add(temp);
                                i = keyList.size();
                
                            }
                        }
                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            throw databaseError.toException();
                        }
                    });
                

                这段代码可以很好地将所有firebase键添加到arraylist中,您可以使用firebase值或其他静态值来完成。

                【讨论】:

                • 不鼓励仅使用代码的答案。请edit您的答案并添加一些文字来解释它如何解决问题和/或它与其他答案的不同之处。
                【解决方案14】:
                    @Override
                       public void onDataChange(DataSnapshot dataSnapshot) {
                           for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                               User user = postSnapshot.getValue(User.class);
                               list.add(user);
                           }
                           for (int i=0;i<list.size();i++)
                           {
                               Log.e("Name",list.get(i).getname());
                               Log.e("Phone",list.get(i).getphone());
                
                           }
                       }
                       @Override
                       public void onCancelled(FirebaseError firebaseError) {
                       Log.e("error",firebaseError.getMessage());
                       }
                   });
                

                类模型

                class User{
                
                String name;
                
                String phone;
                
                public String getname() {
                    return name;
                }
                
                public void setname(String name) {
                    this.name = name;
                }
                
                
                public String getphone() {
                    return phone;
                }
                
                public void setphone(String phone) {
                    this.phone = phone;
                }
                }
                

                列表绑定

                List<User> list= new ArrayList <>();
                

                这项工作适合你

                【讨论】:

                  【解决方案15】:
                  DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
                          DatabaseReference mMainMenuRef = mRootRef.child("tut_master");//main
                          DatabaseReference mSubMenuRef = mMainMenuRef.child("english");//sub
                          List<Tutorial>   tutorialNames=new ArrayList<>();
                          mSubMenuRef.addValueEventListener(new ValueEventListener() {
                              @Override
                              public void onDataChange(DataSnapshot dataSnapshot) {
                  
                                  for(DataSnapshot ds : dataSnapshot.getChildren()) {
                                      long id = ds.child("id").getValue(Long.class);
                                      String name = ds.child("name").getValue(String.class);
                  
                                      Tutorial tut = new Tutorial();
                                      tut.setTutId(id+"");
                                      tut.setTutName(name);
                                      tutList.add(tut);
                  
                                  }
                  
                              }
                  
                              @Override
                              public void onCancelled(@NonNull DatabaseError databaseError) {
                  
                              }
                  
                  
                          });
                  

                  【讨论】:

                    【解决方案16】:
                     private FirebaseDatabase firebaseDatabase=  FirebaseDatabase.getInstance();
                        private DatabaseReference databaseReference=  firebaseDatabase.getReference();
                        private DatabaseReference mChildReference= databaseReference.child("data");
                    
                      mChildReference.addValueEventListener(new ValueEventListener() {
                                @Override
                                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                    for(DataSnapshot ds : dataSnapshot.getChildren()) {
                                        User commandObject = ds.getValue(User.class);
                                        Log.d("TAG", commandObject.getMsg());
                                    }
                                    Toast.makeText(MainActivity.this,dataSnapshot.toString(),Toast.LENGTH_SHORT).show();
                                }
                    
                                @Override
                                public void onCancelled(@NonNull DatabaseError databaseError) {
                    
                                }
                            });
                    

                    这会对你有所帮助,你只需要创建一个包含 String msg 的模型类。

                    【讨论】:

                      【解决方案17】:

                      使用 Gson 是我最喜欢的解决方案。

                      mFirebaseRef.addValueEventListener(new ValueEventListener() {
                          @Override
                          public void onDataChange(DataSnapshot dataSnapshot) {
                              Type StringListType = new TypeToken<List<String>>(){}.getType();
                              List<String> td = new Gson().fromJson(dataSnapshot.getValue(), StringListType);
                          }
                      });
                      

                      如果您认为获取 TypeToken 的代码不直观。您可以编写一个类来包含您需要的所有类型。所以下次,你可以快速获得这些类型。

                      class TypeTokens{
                          static public final Type StringListType = new TypeToken<List<String>>(){}.getType();
                          static public final Type StringMapType = new TypeToken<Map<String, String>>(){}.getType();
                          static public final Type LongMapType = new TypeToken<Map<String, Long>>(){}.getType();
                          static public final Type DateMapType = new TypeToken<Map<String, Date>>(){}.getType();
                      }
                      

                      【讨论】:

                        【解决方案18】:

                        如果你使用 Kotlin,下一个是一个很好的解决方案:

                        myRef.addListenerForSingleValueEvent(object : ValueEventListener {
                          override fun onDataChange(dataSnapshot: DataSnapshot) {
                              val list = dataSnapshot.children.map { it.getValue(YourClass::class.java)!! }
                              Log.d("TAG", "Value is: $list")
                        }
                        

                        【讨论】:

                          猜你喜欢
                          • 2018-01-19
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多