在Firebase中更改值会导致无限循环

时间:2020-07-11 02:17:24

标签: android firebase firebase-realtime-database

我想通过单击星号(按钮)来实现“添加到收藏夹”功能。当我第一次单击时,在Firebase中将一个值设置为“用户收藏夹”,并且星星将变为黄色,而当我再次单击时,它将从列表中删除,然后将星星恢复正常。我正在尝试此代码,但是正在循环。我该如何解决?

    final DatabaseReference ref = FirebaseDatabase.getInstance().getReference( "Usuarios" );
    ref.child( mAuth.getUid() ).child( "Favoritos" )
            .addValueEventListener( new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                    if (dataSnapshot.exists()) {
                        botaoFavorito.setImageResource(  R.drawable.ic_favoritos  );
                        ref.child( mAuth.getUid() ).child( "Favoritos" ).child( posicao ).setValue(null);
         
                    }
              else {
                        botaoFavorito.setImageResource(  R.drawable.ic_favorito_adicionado  );
                        ref.child( mAuth.getUid() ).child( "Favoritos" ).child( posicao ).setValue(posicao);
                       
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            } );

2 个答案:

答案 0 :(得分:3)

自从您调用addValueEventListener以来,Firebase会尽快使用当前数据调用onDataChange,然后继续监视数据库中的更改。只要有更改,它就会使用更新的数据再次调用您的onDataChange

在您的onDataChange工具中,您可以通过调用setValue来修改数据。由于该数据位于您正在监听的位置下,因此它将触发监听器,并再次调用您的onDataChange。因此,您得到一个onDataChange-> setValue-> onDataChange-> setValue ....

循环

最简单的解决方案是使用addListenerForSingleValueEvent,它仅获取初始值,并且不会继续监听。这样,您将得到onDataChange-> setValue,仅此而已。

在代码中:

final DatabaseReference ref = FirebaseDatabase.getInstance().getReference( "Usuarios" );
ref.child( mAuth.getUid() ).child( "Favoritos" )
    .addListenerForSingleValueEvent( new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            if (dataSnapshot.exists()) {
                botaoFavorito.setImageResource(  R.drawable.ic_favoritos  );
                ref.child( mAuth.getUid() ).child( "Favoritos" ).child( posicao ).setValue(null);
 
            }
      else {
                botaoFavorito.setImageResource(  R.drawable.ic_favorito_adicionado  );
                ref.child( mAuth.getUid() ).child( "Favoritos" ).child( posicao ).setValue(posicao);
               
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            throw databaseError.toException(); // don't ignore errors
        }
    } );

答案 1 :(得分:1)

您需要使用addListenerForSingleValueEvent而不是addValueEventListener

  • addValueEventListener-持续连续列出事件。
  • addListenerForSingleValueEvent-聆听 仅第一个事件

在您的代码中,只需将addValueEventListener替换为addListenerForSingleValueEvent,仅需保留代码的其余部分即可。