【问题标题】:How to completely remove the value from the Firebase Realtime Database?如何从 Firebase 实时数据库中完全删除值?
【发布时间】:2019-02-18 11:10:03
【问题描述】:

我在数据库中创建了一个数组。通过应用程序的代码,我从数组中获取值并且我想将其删除,但是为了使代码能够工作,我希望将值完全删除,也就是说,数组必须以“0”重新开始,但在帮助下removeValue () 命令的它只是分配一个空值。如何从数据库中删除一个值?

我尝试了removeValuesetValue (null),但它仍然将基数中的值替换为null。

import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.Map;

public class MainActivity extends AppCompatActivity {

    Button mButtonSee;
    TextView mTextViewPromo;

    DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
    DatabaseReference mPromoRef =                 
mRef.child("delivery").child("0").child("promokod");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mButtonSee = findViewById(R.id.buttonSee);
        mTextViewPromo = findViewById(R.id.promo);

        mButtonSee.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                mPromoRef.addListenerForSingleValueEvent(new 
ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    String text = dataSnapshot.getValue(String.class);
                    mTextViewPromo.setText(text);
                    mPromoRef.removeValue();
                }

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

                    }

                });

            }
        });

    }
}

因此,当我单击按钮时,我想从第一个数组中获取一个值,然后再次删除它以再次从新的第一个数组中获取值。

它的数据库结构:

我的新代码:

public class MainActivity extends AppCompatActivity {


Button mButtonSee;
TextView mTextViewPromo;


DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mPromoRef = mRef.child("delivery");


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    mButtonSee = findViewById(R.id.buttonSee);
    mTextViewPromo = findViewById(R.id.promo);


    mButtonSee.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            mPromoRef.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    LinkedList<String> values = new LinkedList<>();
                    boolean isFirst = true;
                    for (DataSnapshot codeSnapshot: dataSnapshot.getChildren()) {
                        if (isFirst) {
                            isFirst = false;
                        }
                        else {
                            String text = codeSnapshot.getValue(String.class);
                            values.add(text);
                        }
                    }
                    mPromoRef.setValue(values);
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    throw databaseError.toException();
                }

            });

        }
    });

}
}

和 logcat:2019-02-20 02:11:25.263 1631-2110/? E/AudioFlinger:AudioTrack size=131296 内存不足

2019-02-20 02:11:25.263 1631-2110/? E/AudioFlinger: createRecordTrack_l() initCheck failed -12;没有控制块?

2019-02-20 02:11:25.267 1631-12210/? I/AudioFlinger:AudioFlinger的线程0xef703a00 tid=12210准备运行

2019-02-20 02:11:25.269 2651-11949/com.google.android.googlequicksearchbox:search E/IAudioFlinger: createRecord 返回错误 -12

2019-02-20 02:11:25.269 2651-11949/com.google.android.googlequicksearchbox:search E/AudioRecord:AudioFlinger 无法创建记录轨道,状态:-12

2019-02-20 02:11:25.271 2651-11949/com.google.android.googlequicksearchbox:search E/AudioRecord-JNI:创建 AudioRecord 实例时出错:初始化检查失败,状态为 -12。

2019-02-20 02:11:25.274 2651-11949/com.google.android.googlequicksearchbox:search E/android.media.AudioRecord:初始化本机 AudioRecord 对象时出现错误代码 -20。

2019-02-20 02:11:25.274 2651-11949/com.google.android.googlequicksearchbox:search I/MicrophoneInputStream: mic_started SR : 16000 CC : 16 SO : 6

2019-02-20 02:11:25.275 2651-11949/com.google.android.googlequicksearchbox:search E/ActivityThread:找不到 com.google.android.apps.gsa.testing.ui 的提供商信息。录音.

运行:

E/AndroidRuntime: 致命异常: main 进程:com.example.ru.puddig,PID:12504 com.google.firebase.database.DatabaseException:无法将 java.util.HashMap 类型的值转换为字符串 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(com.google.firebase:firebase-database@@16.0.6:413) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@16.0.6:199) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@16.0.6:79) 在 com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@16.0.6:212) 在 com.example.ru.puddig.MainActivity$1$1.onDataChange(MainActivity.java:54) 在 com.google.firebase.database.Query$1.onDataChange(com.google.firebase:firebase-database@@16.0.6:183) 在 com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database@@16.0.6:75) 在 com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database@@16.0.6:63) 在 com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database@@16.0.6:55) 在 android.os.Handler.handleCallback(Handler.java:873) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:193) 在 android.app.ActivityThread.main(ActivityThread.java:6669) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

【问题讨论】:

  • 请添加您使用removeValue方法的代码和您的数据库结构。
  • 添加removeValue的代码
  • 我改了代码,不好意思,没注意到我删了行

标签: android firebase firebase-realtime-database


【解决方案1】:

请查看this firebase blog,他们在其中提到如何将数组与 firebase 一起使用。总结一下您的问题,请从博客中获取以下观点。

  • 要删除键,我们保存整个数组而不是使用 .remove()

【讨论】:

  • 是的,我看到了这个博客,但我不明白如何在我的情况下实现它
【解决方案2】:

正如 Jainam 链接的文章所解释的,要从数组的开头删除一个项目,您需要加载整个数组,删除项目客户端,然后将整个数组写回。在这样的代码中:

DatabaseReference mRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mPromoRef = mRef.child("delivery");
mPromoRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        List<String> values = new LinkedList<String>();
        boolean isFirst = true;
        for (DataSnapshot codeSnapshot: dataSnapshot.getChildren()) {
            if (isFirst) {
                isFirst = false;
            }
            else {
                String text = codeSnapshot.getValue(String.class);
                values.add(text);
            }
        }
        mPromoRef.setValue(values);
    }

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

如您所见,这涉及很多。这样做的原因是,在数组中,每个(但最后一个)元素的键/索引取决于那里的其他元素。因此,从数组中删除一个元素(但最后一个元素)意味着需要更新/移动许多其他元素。出于这个原因,你应该只在你的数据确实需要一个数组时才使用数组,这意味着:如果相同的值可以在集合中多次出现,如果必须保持集合中值的顺序,并且它对你的键是顺序/数字的应用程序。

如果第三个条件不适用,我强烈建议您使用 Firebase 的内置推送 ID 作为密钥。这就是 Jainam 所指的博客文章所描述的内容。

但是,如果您的值在集合中必须是唯一的,并且顺序并不重要,那么您最好使用类似集合的数据结构。在 Firebase 实时数据库中,这看起来像:

{
    "del1": true,
    "del2": true,
    "del3": true
}

这里的值 true 并不重要,因为 Firebase 无法存储没有值的键。重要的是我们现在有一个包含三个键的集合,它们保证是唯一的,并且都可以原子地添加/删除,而无需知道其他键。

如果您对上述结构有一个DatabaseReference,则可以使用以下更简单的代码从中删除"del1"

ref.child("del1").removeValue();

有关此结构的更多信息,请参阅我的回答:Firebase query if child of child contains a value

【讨论】:

  • 我添加了你写的代码,但是程序崩溃了
  • 这些信息不足以帮助您进一步了解。如果程序崩溃,请显示您可以在 logcat 中找到的错误消息和堆栈跟踪。
  • 好的,现在作为回复,我将编写更改的代码并从 logcat 复制错误
  • 错误消息“没有足够的内存用于 AudioTrack size=131296”似乎表明没有足够的内存来加载音轨。我怀疑这是由于我共享的代码不正确造成的。
  • 可能,但是如何解决它,我是否正确实现了您的代码?
猜你喜欢
  • 2016-09-20
  • 2018-02-03
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多