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

Có *_*Văn 6 java android firebase firebase-realtime-database

我想从 android 中的 Firebase 获取所有餐馆列表。 我的数据库

这是我的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

但我有一个例外

Expected a List while deserializing, but got a class java.util.HashMap
Run Code Online (Sandbox Code Playgroud)

在 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);
}
Run Code Online (Sandbox Code Playgroud)

但我仍然有这个例外(:.

任何人都可以知道为什么?

有解决方案吗?

非常感谢!

Ale*_*amo 3

您的代码中有两个问题。第一个错误是这样的:

反序列化时需要一个 List,但得到一个类 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);
Run Code Online (Sandbox Code Playgroud)

第二个问题是你现在无法返回尚未加载的内容。Firebase API 是asynchronous,这意味着该onDataChange()方法在调用后立即返回,并且稍后将调用它返回的任务的回调。无法保证需要多长时间。因此,可能需要几百毫秒到几秒的时间才能获得数据。由于该方法立即返回,因此listRes由于该方法的异步行为,您尝试返回的列表将为空。

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

解决此问题的一个快速解决方案是listRes仅在onDataChange()方法内部使用列表(如上面的代码行所示),否则我建议您查看这篇文章中我答案的最后部分,其中我解释了如何完成它使用自定义回调。您还可以观看此视频以更好地理解。

编辑:

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);
}
Run Code Online (Sandbox Code Playgroud)