首页 > 解决方案 > 更改 Firebase 中的值会导致无限循环

问题描述

我想通过单击星号(按钮)来实现“添加到收藏夹”的功能。当我第一次单击时,在 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) {

                }
            } );

标签: androidfirebasefirebase-realtime-database

解决方案


由于您正在调用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
        }
    } );

推荐阅读