首页 > 解决方案 > 使用 removeValue() 删除 firebase 子时,应用程序因 IndexOutOfBoundsException 而崩溃

问题描述

我正在制作一个基于firebase Realtime database的 android 应用程序。我正在读取RecyclerView. 我的RecyclerView.

  1. 文本视图 = 名称
  2. 文本视图 = 数字
  3. 按钮 = 删除

当我从我的RecyclerView三件事中删除一些孩子时,可能会发生:

  1. 有时它会正常删除目标孩子

  2. 有时它会删除其他一些孩子(通常在目标孩子之下。)

  3. 有时我的应用程序崩溃。

这是我的适配器的代码:

public class holder extends RecyclerView.ViewHolder {
    public Button btnDelete;
    public TextView tvName;
    public TextView tvRoll;

    public holder(@NonNull View itemView) {
        super(itemView);
        btnDelete=(Button) itemView.findViewById(R.id.idDelete);
        tvName=(TextView) itemView.findViewById(R.id.idName);
        tvRoll=(TextView) itemView.findViewById(R.id.idRoll);

    }
}

这是在回收站视图中显示项目的代码和删除按钮的代码:

options = new FirebaseRecyclerOptions.Builder<basic>()
                .setQuery(myRef, basic.class)
                .build();
        adapter = new FirebaseRecyclerAdapter<basic, holder>(options) {
            @SuppressLint("SetTextI18n")
            @Override
            protected void onBindViewHolder(@NonNull holder holder, final int i, @NonNull final basic basic) {
                holder.tvName.setText(basic.getFb01name());
                holder.tvRoll.setText(basic.getFb04roll());
                holder.btnDelete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                            myRef.child(getRef(i).getKey()).removeValue();
                    }
                });
            }

            @NonNull
            @Override
            public holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
                return new holder(v);
            }
        };
        //------------------------------
        adapter.startListening();
        Userlist.setAdapter(adapter);
        //-----------------------------------

我猜不出问题出在哪里。

还请提供一个实用的解决方案。

这是崩溃报告:

2020-11-30 23:27:45.968 10796-10796/com.my App Name E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.my App Name, PID: 10796
    java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
        at java.util.ArrayList.get(ArrayList.java:437)
        at com.firebase.ui.common.BaseObservableSnapshotArray.getSnapshot(BaseObservableSnapshotArray.java:70)
        at com.firebase.ui.database.FirebaseRecyclerAdapter.getRef(FirebaseRecyclerAdapter.java:112)
        at com.my App Name.ViewActivity$1$1.onClick(ViewActivity.java:72)
        at android.view.View.performClick(View.java:7448)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2020-11-30 23:27:46.701 1467-10685/com.google.android.googlequicksearchbox E/sb.v.u.LiteSuggestSourc: On-device lite suggest model loading error.
2020-11-30 23:27:46.818 1467-1774/com.google.android.googlequicksearchbox E/MDD: DownloadProgressMonitor: Can't find file group for uri: android://com.google.android.googlequicksearchbox/files/sharedminusonemodule/shared/SharedMinusOneData.pb.tmp

标签: javaandroidfirebase-realtime-databasefirebaseui

解决方案


似乎当您getRef(i)在按钮onClick回调中访问 Firebase 时,它​​可以引用错误的位置i导致IndexOutOfBoundsException

因此,我们将在回调之外获取密钥,如下所示:

options = new FirebaseRecyclerOptions.Builder<basic>()
            .setQuery(myRef, basic.class)
            .build();
    adapter = new FirebaseRecyclerAdapter<basic, holder>(options) {
        @SuppressLint("SetTextI18n")
        @Override
        protected void onBindViewHolder(@NonNull holder holder, final int i, @NonNull final basic basic) {
            holder.tvName.setText(basic.getFb01name());
            holder.tvRoll.setText(basic.getFb04roll());
            String refKey = getRef(i).getKey(); // <<<<<< Here is the change
            
            holder.btnDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    myRef.child(refKey)).removeValue();
                }
            });
        }

        @NonNull
        @Override
        public holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
            return new holder(v);
        }
    };

推荐阅读