By doubling the value returned when running onDataCahage in FIREBASE, can you help me?

Asked

Viewed 53 times

-2

I want to recover the value of a drive in Firebase and save that value whenever the field flag for "noDebitado" and thereafter, with each loop interaction for, I want to set a new value for flag inside the Firebase to "debitado".

By doing so I can get the value of each drive:

public void pegarValorMov(){
    String emailUsuario = autenticacao.getCurrentUser().getEmail();
    String idUsuario = Base64Custon.codificarBase64(emailUsuario);
    movimentacaoRef = firebaseRef.child("movimentacao").child( idUsuario).child( mesAnoSelecionado );

    valueEventListenerMov = movimentacaoRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {

            for (DataSnapshot dados : snapshot.getChildren()) {
                Movimentacao movimentacao = dados.getValue(Movimentacao.class);

                //retornando o nó principal de cada movimentacao
                key = dados.getKey();

                if (movimentacao.getFlag().equals("noDebitado")) {
                    //recupera o valor da movimentaçao
                    valorReceita = movimentacao.getValor();

                    //exibe o valor da movimentacao atual
                    Log.i("VALOR", "Valor Receita " + valorReceita );

                    //soma o valor da movimentação a cada interaçao
                    vReceita = vReceita + valorReceita;

                }

            }//fim do for

            //exibe o valor total das movimentacoes encontradas para futuros calculos
            Log.i("VALOR", "Valor Receita total " + vReceita );

        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
        }
    });
}

inserir a descrição da imagem aqui

inserir a descrição da imagem aqui

I wish to change the value of flag whenever she is equal to "noDebitado", I tried to do this by adding the following line of code inside the block if.

            if (movimentacao.getFlag().equals("noDebitado")) {
                //recupera o valor da movimentaçao
                valorReceita = movimentacao.getValor();

                //exibe o valor da movimentacao atual
                Log.i("VALOR", "Valor Receita " + valorReceita );

                //soma o valor da movimentação a cada interaçao
                vReceita = vReceita + valorReceita;

                //trecho que alterar o valor da flag no firebase
                movimentacaoRef.child(key).child("flag").setValue("debitado");

            }

It worked, the value of flag in Firebase was changed, but it emits a slightly strange result (image below), so the value of each drive repeated, as if the loop for run more times than the amount of items in Firebase.

inserir a descrição da imagem aqui

... found some issues about the onDataChange run more than once when a data is changed in Firebase, but got a little confused.

2 answers

0

I don’t quite understand the code and its intent. But there are some details you need to know about the Realtime Database. Note that you are initially creating a "moverRef" system so any modified data will add the onDataChange Trigger and run its function. I noticed that within onDataChange you modify the database reference itself. Be careful with this because you can create an infinite loop in RTDB (actually creating).

The most conducive and safe way to do this would be to make a transaction (https://firebase.google.com/docs/database/android/read-and-write?hl=pt-br#save_data_as_transactions) so you can run several updates atomically.

another option is to create a System, read the database only once using get().addOnCompleteListener. So you prevent unwanted loops.

A rule to make database and your app work better and remember that once you own a Listener avoid making multiple separate recordings whether parallel or consecutive. try grouping everything preferably into one Transaction.

Finally, it is sometimes better to not even run in the client’s app certain types of code that make calculations in the database. in these situations it is preferred to use the backend. I even recommend Firebase functions.

  • Thank you for contributing Paul, your help helped me to find the solution. Actually when the "flag" was changed onDataChange was triggered again, thus generating "loop" (callback). And actually change the value of the "flag" directly , like this: moverRef.Child(key). Child("flag"). setValue("debited"); is not very suitable, so I created an update method within the class to be triggered when desired. Vlw, hug.

0


As I mentioned, the onDataChange performs more "calls" when there is data change, so it seems to "repeat" the values. Simply consulting the documentation I found the solution by adding only a single line:

// Remove listener
ref.removeEventListener(listener);

This is used to disconnect callbacks.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.