java - 使用 recyclerview 的“onChildRemoved”方法出错
问题描述
我正在用来自 firebase 的数据填充我的 recyclerview(它被放入一个卡片视图中,上面有 3 个文本视图)。当我从 Firebase 中删除它时,它仍会显示在应用程序中,除非我重新启动它。我尝试在 onChildRemoved 方法中做一些事情,但我不断收到错误消息。这是我的错误(运行“list.remove(index)”时发生):
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.samuelford48gmail.thsconnect, PID: 11463
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
at java.util.ArrayList.remove(ArrayList.java:506)
at com.samuelford48gmail.thsconnect.home_fragment$1.onChildRemoved(home_fragment.java:140)
这是我的代码:
public class home_fragment extends Fragment{
private FirebaseDatabase database;
private DatabaseReference myRef;
private List<Listdata> list;
private RecyclerView recyclerview;
public home_fragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.home_fragment, container, false);
final List<String> keyList = new ArrayList<String>();
recyclerview = (RecyclerView) view.findViewById(R.id.rview);
database = FirebaseDatabase.getInstance();
myRef = database.getReference("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).child("Classes");
list = new ArrayList<>();
myRef.addChildEventListener(new ChildEventListener() {
final adapter_user_remove_class recycler = new adapter_user_remove_class(list);
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, String s) {
String class_id = dataSnapshot.getValue(String.class);
myRef = database.getReference("Classes").child(class_id).child("class_info");
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
keyList.add(dataSnapshot.getKey());
Class_model new_class = dataSnapshot.getValue(Class_model.class);
assert new_class != null;
String nameofclass = new_class.getDate_clasname();
String teacherofclass = new_class.getTeacher();
String roomnumberofclass = new_class.getRoom_number();
String class_key = new_class.getUid();
Listdata listdata = new Listdata(nameofclass, teacherofclass, roomnumberofclass, class_key);
listdata.setDate_class(nameofclass);
listdata.setTeacher(teacherofclass);
listdata.setRnumber(roomnumberofclass);
list.add(listdata);
recycler.notifyDataSetChanged();
}
@Override
public void onCancelled(DatabaseError error) {
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
alertDialog.setTitle("Error");
alertDialog.setMessage("Check your connection! If, problem persists please email svhsdev@vigoschools.org!");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
});
RecyclerView.LayoutManager layoutmanager = new LinearLayoutManager(getContext());
recyclerview.setLayoutManager(layoutmanager);
recyclerview.setItemAnimator(new DefaultItemAnimator());
recyclerview.setAdapter(recycler);
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
int index = keyList.indexOf(dataSnapshot.getKey());
list.remove(index);
keyList.remove(index);
recycler.notifyDataSetChanged();
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(DatabaseError error) {
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
alertDialog.setTitle("Error");
alertDialog.setMessage("Check your connection! If, problem persists please email svhsdev@vigoschools.org!");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
});
return view;
}
}
这是我的数据库结构:
{
"Classes" : {
"-LiGRe3e1YF_HFrHKMgi" : {
"Students" : {
"xfDGLrXF4gP8AJAPtAPc4VMe9y72" : "xfDGLrXF4gP8AJAPtAPc4VMe9y72"
},
"class_info" : {
"date_clasname" : "mm",
"room_number" : "jjhh",
"subject" : "Science",
"teacher" : "mm",
"uid" : "-LiGRe3e1YF_HFrHKMgi"
}
},
"Users" : {
"xfDGLrXF4gP8AJAPtAPc4VMe9y72" : {
"Classes" : {
"-LiGRe3e1YF_HFrHKMgi" : "-LiGRe3e1YF_HFrHKMgi",
},
"User_info" : {
"email" : "c@gmail.com",
"grade" : "2",
"name" : "n",
"uid" : "xfDGLrXF4gP8AJAPtAPc4VMe9y72"
}
}
}
}
解决方案
因此,通常当您处理 Firebase 数据并将其呈现在 RecyclerView 中时,我的偏好是监听 Firebase 数据库中的整个节点。
您将快照中的数据映射到一个列表中,其中 N 是您的数据项的一些 POJO 表示,然后您使用整个列表更新您的适配器。
在适配器内部,可以更新内部列表,然后使用DiffUtil
public class N {
final String id; // Firebase key
public N(String id) { }
public String getId() { return id; }
}
fb.collection("/path/to/collection")
.addEventListener(snapshot -> {
List<N> list = new ArrayList();
for (...) { /* create and add Ns to list */ }
adapter.setList(list);
});
// in your adapter...
void setList(List<N> items) {
List<N> oldList = data;
data = items;
// Updates your list, applys animations, etc.
DiffUtil.calculateDiff(new Callback(oldList, data).dispatchUpdatesTo(this);
}
class Callback implements DiffUtil.Callback {
// impl, pretty straightforward
}
这样做意味着您不需要在其他地方管理键/值。
https://developer.android.com/reference/android/support/v7/util/DiffUtil
推荐阅读
- javascript - 在 socket.io 中收集套接字返回的结果
- spring - How to use current exchange and queue name of rabbitmq with spring cloud stream rabbitmq
- python-3.x - 使用 Splinter 在网站的 textarea 中填充表格或值列表
- android - 使 onClickListener 成为静态方法
- sql-server - 如何在 SQL Server 2014 中实现行级安全性
- reactjs - React 找不到组件
- jmeter - 如何创建正则表达式以从字符串响应中提取值?
- javascript - 如果已经执行,Javascript 函数会阻止执行
- python - 从输入中获取值
- python - 是否可以通过给定的向量平铺每一行不同的时间