Код Android не работает последовательно, когда я использую базу данных FirebaseReference в этом конкретном случае

Здесь задача (объект) сохраняется в базу данных fireBase, но для установки ListID и ID есть несколько условий:

  1. если это первая задача пользователя, установите для обоих значение 20k

  2. если у пользователя уже есть списки задач в firebase, добавьте listId этого списка задач к текущему listID задачи и добавьте (ID последней задачи пользователя + 1) к идентификатору текущей задачи.

Какой я хочу видеть последовательность (см. Операторы Log.e(..) в коде):

1-> 2-> 3-> 4-> 5-> 6-> 7

Что происходит на самом деле: 1-> 4-> 5-> 7-> 2-> 3

(Кроме того, Никогда не переходить на 6... Для чего я сослался на следующее: Не удается добраться до некоторых строк при отладке приложения для Android & Точка останова Android Studio Gradle Не найден исполняемый код в строке ...... Но все напрасно)

( DBToFireb(..) - это метод, в котором changeListener используется внутри onComplete(..) из DatabaseReference.CompletionListener() )

public static boolean addTaskToFireBase(final Activity activity, final com.rb.eztask.model.TodoTask task, final ChangeListener changeListener)
    {

        mDatabase=FirebaseDatabase.getInstance().getReference("tasks");
        final String taskId = mDatabase.push().getKey();
        task.setTaskId(taskId);
        final DatabaseReference myFieBaseDBChecker=FirebaseDatabase.getInstance().getReference("users").
                child(Userkey).child("tasks");
        myFieBaseDBChecker.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                String s=dataSnapshot.getValue().toString();
                if(s!=null)
                {
                    if(s.contentEquals(","))
                    {
                        task.setId(20000);
                        task.setListId(20000);
                        task.setKey(UserKey);
                        DBToFireb(activity, taskId, task, changeListener);
                    }

                    else
                    {   String tasks[]=s.split(",");
                        final String lastTask = tasks[tasks.length-1];
                        DatabaseReference compareDb;

                        for(int i=0;i<tasks.length;i++)
                        {
                            if(tasks[i].length()>2)
                            {Log.e("im","1");
                               compareDb=FirebaseDatabase.getInstance().getReference("task").child(tasks[i]);
                                compareDb.addListenerForSingleValueEvent(new ValueEventListener() {
                                    @Override
                                    public void onDataChange(DataSnapshot dataSnapshot) {
                                        Log.e("im","2");
                                        TodoTask taskToCompare=dataSnapshot.getValue(TodoTask.class);
                                        Log.e("im","3");
                                        if(taskToCompare.getBasketName().equals(task.getBasketName()))
                                        {
                                            task.setListId(taskToCompare.getListId());
                                        }
                                    }

                                    @Override
                                    public void onCancelled(DatabaseError databaseError) {

                                    }
                                });
                            }
                        }


                        Log.e("im","4");
                        compareDb=FirebaseDatabase.getInstance().getReference("tasks").child(lastTask);
                        Log.e("im","5");
                        compareDb.addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                Log.e("im","6");
                                TodoTask lastTaskInFireB = dataSnapshot.getValue(TodoTask.class);
                                    task.setListId(lastTaskInFireB.getListId()+1);

                                task.setId(lastTaskInFireB.getId()+1);

                                task.setKey(UserKey);
                                DBToFireb(activity, taskId, task, changeListener);
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });
                        Log.e("im","7");
                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        return true;

    }

person Sukesh Panwar    schedule 30.06.2017    source источник
comment
Я не знаю, понимаете ли вы, что Firebase асинхронный   -  person OneCricketeer    schedule 30.06.2017
comment
@cricket_007 как мне решить эту проблему?   -  person Sukesh Panwar    schedule 30.06.2017
comment
Вы пытались распечатать значение lastTask до того, как сделали getReference("tasks").child(lastTask);? Если вы действительно хотите, чтобы все выполнялось в полном порядке, вам придется написать свой код так, чтобы вы создавали новый слушатель Firebase только внутри предыдущего onDataChange, а не после него.   -  person OneCricketeer    schedule 30.06.2017
comment
Кроме того, мы не можем сказать, что String s=dataSnapshot.getValue().toString(); назначается. У вас есть класс задач? Почему бы вам не сделать Task t=dataSnapshot.getValue(Task.class);, если вы это сделаете?   -  person OneCricketeer    schedule 30.06.2017
comment
@cricket_007 lastTask, как и ожидалось, проблема именно в этой последовательности. Нужно ли здесь использовать класс AsynchTask?   -  person Sukesh Panwar    schedule 30.06.2017
comment
Нет. Firebase не нуждается в Asynctask, и это только усложнит ситуацию.   -  person OneCricketeer    schedule 30.06.2017
comment
Вместо того, чтобы объяснять, что ваш код делает (или не делает), объясните словами, что вы хотите, чтобы он делал, с помощью минимально воспроизводимого примера.   -  person OneCricketeer    schedule 30.06.2017


Ответы (1)


onDataChange (и обратные вызовы Firebase в целом) вызываются асинхронно

person John O'Reilly    schedule 30.06.2017
comment
да, подскажите, какое решение? - person Sukesh Panwar; 30.06.2017
comment
Асинхронность является ключевой концепцией в большинстве приложений... Я бы порекомендовал сначала прочитать об этом. Затем вам нужно сделать ваше приложение более реактивным....т.е. разработайте свою логику, чтобы реагировать на асинхронные обновления/события. - person John O'Reilly; 30.06.2017
comment
Не существует решения для асинхронного/реактивного программирования, единственный путь вперед — узнать, как это работает. Я рекомендую прочитать мой ответ здесь: stackoverflow.com/questions/33203379/ - person Frank van Puffelen; 30.06.2017