如何使用 Firebase 处理异步数据库? [英] How to handle asynchronous Database with Firebase?

查看:23
本文介绍了如何使用 Firebase 处理异步数据库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多关于在我的 Android 应用中处理异步数据库的问题.

因为我知道数据库是异步的,所以我尝试了几种方法来处理它.正如您在我的代码中看到的,我有两个函数需要在我的数据库中使用一个数组.我的第一个函数 (setArrayfromDatabase) 将对我的数据库中的数组应用更改,而我的第二个函数 (setAnotherArray) 需要使用这个数组以及从我的第一个函数应用的更改.这是我的代码:

 FirebaseDatabase 数据库 = FirebaseDatabase.getInstance();final DatabaseReference myReff =database.getReference("server").child("user");myReff.addListenerForSingleValueEvent(new ValueEventListener() {@覆盖public void onDataChange(DataSnapshot dataSnapshot) {//从我的数据库中取出数组最终 ArrayListarray_from_database;GenericTypeIndicator>genericTypeIndicator = new GenericTypeIndicator>() {};array_from_database = dataSnapshot.getValue(genericTypeIndicator);System.out.println("1");//在第一个函数中使用这个数组,这个函数会修改它.setArray_for_database(array_from_database);myReff.addValueEventListener(new ValueEventListener() {@覆盖public void onDataChange(DataSnapshot dataSnapshot) {//只有当我的数组被改变时才会执行(所以只有当我的其他函数被正确执行时setAnotherArray(array_from_database);System.out.println("3");}@覆盖public void onCancelled(DatabaseError databaseError) {}});}@覆盖public void onCancelled(DatabaseError databaseError) {}});

这是 setArray_for_database 的代码:

 public void setArray_for_database(ArrayList array_from_database){FirebaseDatabase 数据库 = FirebaseDatabase.getInstance();最终的 DatabaseReference myReff =database.getReference();//从我的数据库中获取数组(在参数中给出)最终 ArrayList数组 = array_from_database;myReff.addListenerForSingleValueEvent(new ValueEventListener() {@覆盖public void onDataChange(DataSnapshot dataSnapshot) {//这将被执行,即使由于方法(addListenerForSingleValueEvent)没有改变数据System.out.println("2");数组.set(0,3);映射<字符串,对象>chemainChild = new HashMap<>();chemainChild.put("服务器/用户/",数组);myReff.updateChildren(chemainChild);}@覆盖public void onCancelled(DatabaseError databaseError) {}});}

这是我的诀窍.在另一个 myReff.addListenerForSingleValueEvent(new ValueEventListener() 中使用 myReff.addValueEventListener(new ValueEventListener()) 的目的是仅在我的数据库数组发生更改时才执行 onDataChange. 但问题是,事实并非如此.这是首先打印的内容:1, 3, 2 而不是 1, 2, 3 就像我期待的那样.

你能帮我吗?我是否以错误的方式处理问题?如果我的数组已更改,我该怎么做才能只执行我的第二个函数?在执行其他操作之前,如何让我的代码等待数据库中的更改?
希望您已经理解我,如果您不理解我的问题,请随时向我提问.

解决方案

改变这个:

 myReff.addValueEventListener(new ValueEventListener() {@覆盖public void onDataChange(DataSnapshot dataSnapshot) {//只有当我的数组被改变时才会执行(所以只有当我的其他函数被正确执行时setAnotherArray(array_from_database);System.out.println("3");}

为此:

final FirebaseDatabase 数据库 = FirebaseDatabase.getInstance();最终 DatabaseReference myReff = database.getReference();myReff.addValueEventListener(new ValueEventListener() {@覆盖public void onDataChange(DataSnapshot dataSnapshot) {DatabaseReference ref2 = database.getReference();//从我的数据库中获取数组(在参数中给出)最终 ArrayList数组 = array_from_database;System.out.println("2");数组.set(0,3);映射<字符串,对象>chemainChild = new HashMap<>();chemainChild.put("服务器/用户/",数组);myReff.updateChildren(chemainChild);System.out.println("3");}

上面可能缺少某些代码,但您可以添加方法 public void setArray_for_database(ArrayList array_from_database){ 中的代码以使其工作.>

由于 onDataChange 是异步的,这意味着程序将继续执行,即使数据仍未检索到,这是唯一的方法.

你得到 1-3-2 的原因是:

  1. 它进入了第一个 onDataChange
  2. 它打印了1"
  3. 它进入了第一个内部的第二个 onDataChange.
  4. 它打印3",因为它是异步的,然后在检索数据时
  5. 它调用方法并打印2"

所以最好在onDataChange

里面的方法中添加数据

以上将解决您在问题中遇到的异步问题.但您确实应该对数据进行非规范化.

阅读本文以了解更多信息:https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html

I have a lot of questions about handeling asynchronous database in my Android app.

Since I know that database is asynchronous, I've tried several things to handle it. As you can see in my code, I've two functions who need to use an array in my database. My first function (setArrayfromDatabase) will apply changes on my array in my database and my second function (setAnotherArray)need to use this array with changes applied from my first function. Here's my code :

    FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myReff =database.getReference("server").child("user");

    myReff.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

        //Take the array from my database
        final ArrayList<Integer> array_from_database;
        GenericTypeIndicator<ArrayList<Integer>> genericTypeIndicator = new GenericTypeIndicator<ArrayList<Integer>>() {};
        array_from_database = dataSnapshot.getValue(genericTypeIndicator) ;

        System.out.println("1");

        //use this array in this first function, and this function will modify it.
        setArray_for_database(array_from_database);

        myReff.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                //this will be executed only if my array is changed (So only if my other function have been correctly executed
                setAnotherArray(array_from_database);
                System.out.println("3");
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {}
        });
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

Here's the code for setArray_for_database :

    public void setArray_for_database(ArrayList<Integer> array_from_database){

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    final DatabaseReference myReff =database.getReference();

    //Take the array from my database (gived in parameter)
    final ArrayList<Integer> array = array_from_database;

    myReff.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            //this will be executed, even if data hasn't been changed because of the method (addListenerForSingleValueEvent)

            System.out.println("2");

            array.set(0,3);

            Map<String, Object> chemainChild = new HashMap<>();
            chemainChild.put("server/user/",array);

            myReff.updateChildren(chemainChild);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

Here's my trick. The purpose of having an myReff.addValueEventListener(new ValueEventListener()inside another myReff.addListenerForSingleValueEvent(new ValueEventListener() is to only execute onDataChange if my array from database has been changed. But the problem is that it's not the case. Here's what's print first : 1, 3, 2 instead of 1, 2, 3 like I'm expecting with my trick.

Can you help me ? Am I handling the problem in the wrong way ? How must I do to only execute my second function, in condition that my array has been changed ? How can I keep my code waiting for changes in my database before executing something else ?
Hope you have understood me and feel free to ask me question if you doesn't understand something in my problem.

解决方案

Change this:

   myReff.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            //this will be executed only if my array is changed (So only if my other function have been correctly executed
            setAnotherArray(array_from_database);
            System.out.println("3");
        }

to this:

final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myReff = database.getReference();

  myReff.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

          DatabaseReference ref2 = database.getReference();

          //Take the array from my database (gived in parameter)
          final ArrayList<Integer> array = array_from_database;
           System.out.println("2");

        array.set(0,3);

        Map<String, Object> chemainChild = new HashMap<>();
        chemainChild.put("server/user/",array);

        myReff.updateChildren(chemainChild);

            System.out.println("3");
        }

Some code may be missing from the above, but you get the idea add the code that is in the method public void setArray_for_database(ArrayList<Integer> array_from_database){ for this to work.

Since onDataChange is asynchronous meaning the program will keep executing, even if data is still not retrieved then this is the only way.

The reason you get 1-3-2, is because of this:

  1. It entered the first onDataChange
  2. It printed "1"
  3. It entered the second onDataChange that is inside the first.
  4. It printed "3" since it is asynchronous, then when the data was retrieved
  5. It called the method and printed "2"

So the best thing is to add the data in the method inside the onDataChange

The above will fix the asynchronous problem that you had in the question. But you really should denormalize your data.

Read this to learn more: https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html

这篇关于如何使用 Firebase 处理异步数据库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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