代码之家  ›  专栏  ›  技术社区  ›  Có Tạ Văn

android在反序列化时需要一个列表,但得到了一个类java.util.hashmap

  •  2
  • Có Tạ Văn  · 技术社区  · 6 年前

    我想从Android的FireBase中获取所有餐馆的列表。 my database

    这是我的代码:

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

    但我有个例外

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

    at restaurantmodel restaurantmodel=datavalues.getValue(restaurantmodel.class);

    更新: 基于Alex Mamo Answser,我更改了我的代码:

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

    但我还是有例外(:。

    有人知道为什么吗?

    有解决办法吗?

    非常感谢!

    1 回复  |  直到 6 年前
        1
  •  2
  •   Alex Mamo    6 年前

    代码中有两个问题。第一个错误是:

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

    可以使用以下代码行来解决:

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

    第二个问题是你现在不能返回还没有加载的东西。FireBase API是 asynchronous ,意思是说 onDataChange() 方法在调用后立即返回,稍后将调用它返回的任务的回调。不能保证要花多长时间。所以可能需要几百毫秒到几秒钟的时间才能得到这些数据。因为该方法立即返回, listRes 由于此方法的异步行为,您尝试返回的列表将为空。

    基本上,您尝试从异步API同步返回一个值。这不是个好主意。您应该按预期异步处理这些API。

    这个问题的一个快速解决方法是使用 列表 仅在 OnDataChange()。 方法(如上述代码行中所示),否则我建议您从中看到我的anwser的最后一部分。 post 其中,我已经解释了如何使用自定义回调来完成它。你也可以看看这个 video 为了更好的理解。

    编辑:

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