Android-Expected a List while deserializing, but got a class java.util.HashMap

后端 未结 5 1087
小蘑菇
小蘑菇 2021-01-18 23:07

I want to get all list of restaurants from Firebase in android.

Here is my code:

boolean delivery;
String openTime, closeTime, restaurantName;
long          


        
5条回答
  •  野的像风
    2021-01-18 23:13

    There are two problems in your code. The first one would be this error:

    Expected a List while deserializing, but got a class java.util.HashMap

    Which can be solved using the following lines of code:

    ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            List 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);
    

    And the second problem is that you cannot return something now that hasn't been loaded yet. Firebase APIs are asynchronous, meaning that onDataChange() method returns immediately after it's invoked, and the callback from the Task it returns will be called sometime later. There are no guarantees about how long it will take. So it may take from a few hundred milliseconds to a few seconds before that data is available. Because that method returns immediately, your listRes list you're trying to return, will be empty due to the asynchronous behavior of this method.

    Basically, you're trying to return a value synchronously from an API that's asynchronous. That's not a good idea. You should handle the APIs asynchronously as intended.

    A quick solution to this problem would be to use the listRes list only inside the onDataChange() method (as in the above lines of code), otherwise I recommend you see the last part of my answer from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

    Edit:

    public void getAllRestaurant(){
        ValueEventListener valueEventListener = new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                List 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);
    }
    

提交回复
热议问题