Android:在服务类的首次初始化过程中,从Firebase获取Pojo列表 [英] Android: Get a Pojo List from Firebase during the first initialization from the Service Class

查看:105
本文介绍了Android:在服务类的首次初始化过程中,从Firebase获取Pojo列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从Firebase获取所有"Baustelle" Pojos的列表.我的服务类是Singelton,在构造函数中,我调用方法initialize,该方法调用方法readAll().那么,为什么"readAll()"不能正常工作?返回后很长时间运行onDataChange,因此它返回null而不是Pojo List.

I try to get a List of all my "Baustelle" Pojos from Firebase. My Service Class is a Singelton and in the Constructor I call the method initialize which calls the Method readAll(). So why is "readAll()" not working correctly ? It runns the onDataChange long after the return so it returns null instead of the Pojo List.

服务

public class Service {
    private static volatile Service instance = null;
    private List<Baustelle> bauList = new LinkedList<>();
    private BaustellenDao bauDao = new BaustellenDao();


    public void initialize(){
       bauList = bauDao.readAll();
    }

   private Service(){
        initialize();
    }

    public static synchronized Service getInstance(){
        if(instance==null)
            instance = new Service();
        return instance;
    }
}

DAO

DAO

public class BaustellenDao implements BaseDao<Baustelle> {
    private FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference("baustellen");
    private List<Baustelle> pojoList=  null;


    @Override
    public List<Baustelle> readAll() {
        // Read from the database

        myRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                    pojoList= new LinkedList<>();
                for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
                    pojoList.add(postSnapshot.getValue(Baustelle.class));
                }




            }

            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.w(TAG, "Failed to read value.", error.toException());
            }
        });


        return pojoList;
    }
} 

推荐答案

数据是从Firebase异步加载的.

Data is loaded from Firebase asynchronously.

由于从服务器返回数据可能要花费一些时间,并且在这段时间内阻止应用程序将导致应用程序无响应"对话框,因此Firebase允许您的应用程序代码在加载数据库时继续运行.然后,当数据从服务器返回时,Firebase客户端会使用该数据调用您的onDataChange方法.

Since it may take quite some time for the data to come back from the server, and blocking the application during this time would lead to an "Application Not Responding" dialog, Firebase allows your application code to continue while it's loading the database. Then when the data comes back from the server, the Firebase client calls your onDataChange method with that data.

最简单的方法是在代码中添加一些日志语句:

The easiest way to see this is by adding a few log statements in your code:

public List<Baustelle> readAll() {
    Log.i(TAG, "Before attaching listener");
    myRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Log.i(TAG, "Inside onDataChange");
        }

        @Override
        public void onCancelled(DatabaseError error) {
            Log.w(TAG, "Failed to read value.", error.toException());
        }
    });
    Log.i(TAG, "After attaching listener");
}

如果运行此代码,则输出为:

If you run this code the output is:

在附加侦听器之前

Before attaching listener

附加监听器后

内部onDataChange

Inside onDataChange

这可能不是您期望的顺序.但这很好地说明了为什么pojoList返回时为空:数据尚未加载.

That is probably not the order you expected. But it explains perfectly why the pojoList is empty when you return it: the data simply hasn't been loaded yet.

无法更改此行为:异步API是针对现代Web API进行应用程序编程所固有的.我发现解决此问题的最好方法是重新设计解决方案.而不是考虑先读取所有数据,然后对其进行处理",而是将其视为开始加载所有数据.每当读取数据时,就对其进行处理."

There is no way to change this behavior: asynchronous APIs are inherent to programming apps against modern web APIs. The best way I've found to deal with this behavior is to reframe my solutions. Instead of thinking "first read all data, then do something with it", I think of it as "Start loading all data. Whenever the data is read, do something with it."

在实践中,这意味着需要数据库中数据的所有代码都必须在方法的内部 中调用.假设您要打印已加载的数据,请执行以下操作:

In practice this means that all code that needs the data from the database needs to be (called from) inside the onDataChange method. So say that you want to print the loaded data, you'd do:

public void readAll() {
    myRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            pojoList= new LinkedList<>();
            for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
                pojoList.add(postSnapshot.getValue(Baustelle.class));
            }
            Log.i(TAG, pojoList);
        }

        @Override
        public void onCancelled(DatabaseError error) {
            Log.w(TAG, "Failed to read value.", error.toException());
        }
    });
}

现在,由于将日志记录编码为 onDataChange,因此这使您的代码不太灵活.因此,您也可以创建自己的回调接口,如我的答案所示: getContactsFromFirebase()方法将返回一个空列表. 对于许多刚接触Firebase的开发人员来说,此主题令人困惑.我强烈建议您查看从此处链接的一些以前的答案.

Now this makes your code a bit less flexible, since you're coding the logging into onDataChange. So you can also create your own callback interface, as shown in my answer here: getContactsFromFirebase() method return an empty list. This topic is confusing for a lot of developers new to Firebase. I highly recommend you check out some of the previous answers that are linked from there.

这篇关于Android:在服务类的首次初始化过程中,从Firebase获取Pojo列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆