Eu quero ficar toda a lista de restaurantes do Firebase no android.
Aqui está o meu código:
boolean delivery;
String openTime, closeTime, restaurantName;
long likes;
List<String> utilities;
List<RestaurantModel> listRes;
DatabaseReference dataResReference;
public RestaurantModel(){
dataResReference = FirebaseDatabase.getInstance().getReference().child("restaurants");
}
public List<RestaurantModel> getallRestaurant(){
listRes = new ArrayList<>();
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataValues : dataSnapshot.getChildren()){
RestaurantModel restaurantModel = dataValues.getValue(RestaurantModel.class);
listRes.add(restaurantModel);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
dataResReference.addListenerForSingleValueEvent(valueEventListener);
return listRes;
}
Mas eu recebo uma exceção
Expected a List while deserializing, but got a class java.util.HashMap
em RestaurantModel restaurantModel = dataValues.getValue (RestaurantModel.class);
Update: Base Alex Mamo answser, eu mudei meu código é:
public void getAllRestaurant(final WhereInterface whereInterface){
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//go to node restaurant because datasnapshot is parent node
DataSnapshot dataSnapshotRes = dataSnapshot.child("restaurants");
//
for (DataSnapshot valueRes : dataSnapshotRes.getChildren()){
RestaurantModel restaurantModel = valueRes.getValue(RestaurantModel.class);
whereInterface.getAllRestaurantModel(restaurantModel);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
databaseReferenceRoot.addListenerForSingleValueEvent(valueEventListener);
}
Mas eu ainda tenho essa exceção (:.
Qualquer um pode saber por quê?
E há solução?
Muito obrigado!
Há dois problemas em seu código. O primeiro seria esse erro:
Esperava uma lista enquanto desserialização, mas tem um java.util.HashMap classe
Que pode ser resolvido usando as seguintes linhas de código:
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
List<RestaurantModel> listRes = new ArrayList<>();
for (DataSnapshot dataValues : dataSnapshot.getChildren()){
RestaurantModel restaurantModel = dataValues.getValue(RestaurantModel.class);
listRes.add(restaurantModel);
}
//Do what you need to do with listRes
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); //Don't ignore errors
}
};
dataResReference.addListenerForSingleValueEvent(valueEventListener);
E o segundo problema é que você não pode retornar algo agora que não foi carregado ainda. APIs Firebase são asynchronous
, o que significa que onDataChange()
método retorna imediatamente depois que ele é invocado, eo retorno da tarefa que retorna será chamado algum tempo depois. Não há garantias sobre quanto tempo vai demorar. Por isso pode levar de algumas centenas de milissegundos para alguns segundos antes que os dados estão disponíveis. Porque esse método retorna imediatamente, a sua listRes
lista que você está tentando retornar, estará vazia devido ao comportamento assíncrono deste método.
Basicamente, você está tentando retornar um valor de forma síncrona a partir de uma API que é assíncrona. Isso não é uma boa idéia. Você deve lidar com as APIs de forma assíncrona como pretendido.
Uma solução rápida para este problema seria a utilização da listRes
lista única dentro do onDataChange()
método (como nas linhas acima de código), caso contrário, eu recomendo que você veja a última parte da minha resposta a partir deste posto em que eu expliquei como isso pode ser feito usando um callback personalizado. Você também pode dar uma olhada neste vídeo para uma melhor compreensão.
Editar:
public void getAllRestaurant(){
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
List<RestaurantModel> listRestaurant = new ArrayList<>();
for (DataSnapshot valueRes : dataSnapshot.getChildren()){
RestaurantModel restaurantModel = valueRes.getValue(RestaurantModel.class);
Log.d("Test", restaurantModel.getRestaurantName());
listRestaurant.add(restaurantModel);
}
//Do what you need to do with listRes
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
};
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
rootRef.child("restaurants").addListenerForSingleValueEvent(valueEventListener);
}