本文介绍了Android在反序列化时期望List,但是得到了一个类java.util.HashMap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从Android中的Firebase获取所有餐厅列表.

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

这是我的代码:

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

在RestaurantModel restaurantModel = dataValues.getValue(RestaurantModel.class);

at RestaurantModel restaurantModel = dataValues.getValue(RestaurantModel.class);

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

Update:Base on Alex Mamo answser, i changed my code is:

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

但我仍然遇到此异常(:.

But i still got this exception (:.

任何人都知道为什么吗?

Anyone can know why?

有解决办法吗?

非常感谢您!

推荐答案

您的代码中有两个问题.第一个是该错误:

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

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

Which can be solved using the following lines of code:

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()方法在调用后立即返回,并且它返回的Task的回调将在以后的某个时间被调用.无法保证需要多长时间.因此,可能需要几百毫秒到几秒钟的时间才能获得该数据.由于该方法会立即返回,因此您尝试返回的listRes列表将由于此方法的异步行为而为空.

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.

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

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.

此问题的快速解决方案是仅在onDataChange()方法内使用listRes列表(如上述代码行),否则我建议您从此 发布 在其中,我已经解释了如何使用自定义回调来完成.您也可以看一下 视频 更好的理解.

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.

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

这篇关于Android在反序列化时期望List,但是得到了一个类java.util.HashMap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 06:17