Issue
I am making an android app based on firebase Realtime database. I am reading the data in a RecyclerView
. There are three items in my RecyclerView
.
When I delete some child from my RecyclerView
three things can happen:
Sometimes it deletes the targeted child normally
Sometimes it deletes some other child (often which is below the targeted child.)
Sometimes my app crashes.
This is the code for my adapter:
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);
}
}
This is the code to show items in recycler view and code for delete button:
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);
//-----------------------------------
I cannot guess where is the problem.
Please also provide a practical solution.
This is the crash report:
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
Solution
It seems that when you access Firebase getRef(i)
within the button onClick
callback, it can reference a wrong position i
causing IndexOutOfBoundsException
So, we'll get the key outside of the callback as below:
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);
}
};
Answered By - Zain
Answer Checked By - Willingham (JavaFixing Volunteer)