如何从 Android 上的 Firebase DataSnapshot 中提取对象列表
Posted
技术标签:
【中文标题】如何从 Android 上的 Firebase DataSnapshot 中提取对象列表【英文标题】:How to extract a list of objects from Firebase DataSnapshot on android 【发布时间】: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)
);
【问题讨论】:
可能重复:***.com/questions/27848313/… 在下面回答。但这部分是一种猜测,因为“它不起作用”非常模糊,而且您没有包含数据的 sn-p。如果我的回答不能解决您的问题:您会遇到什么错误?你的数据是什么样的(复制/粘贴样本,没有截图也没有描述)? 试试这个:***.com/questions/32886546/… 【参考方案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<String, MyDataObject> = (HashMap<String, MyDataObject>) dataSnapshot.getValue();
还是必须将Object 转换为MyDataObject?
@Frank,Android Studio 在这一行显示红色下划线 List
@Frank 谢谢,List<Object> values = td.values();
很高兴知道。
@NarendraBaratam 我有同样的问题。改用这种方式:List<Object> values = new Arraylist<>(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,您必须
-
使用 String 的 HashMap 和您的 Object 初始化 GenericTypeIndicator。
将 DataSnapShot 的值作为 GenericTypeIndicator 获取到 Map。
用 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());
对我来说很好,希望对你有帮助。
【讨论】:
发现这个埋在 doco firebase.com/docs/java-api/javadoc/com/firebase/client/…【参考方案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")
【讨论】:
以上是关于如何从 Android 上的 Firebase DataSnapshot 中提取对象列表的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Android 上的 Firebase 存储正确下载多个文件?
如何从 Android 上的 Firebase DataSnapshot 中提取对象列表
如何从 Android 上的 Firebase DataSnapshot 中提取对象列表
如何在 Android 上的 Firebase 存储中设置持久性?