似乎发生的情况是,如果在Firebase中更改了子项,则recyclerview会使用更改后的值替换最顶层的项目。
例如,如果我要用“化学”改变“微积分”,它将取代生物学,约翰,下午7点与化学,约翰,晚上8点(当然仅在回收者视图本身)。只有在使用recreate()重新启动活动时才会更正recyclerview。 onChildRemoved发生同样的问题,因为最顶层的条目被删除(在recyclerview中)而不是实际从数据库中删除的条目。
当我更改数据库引用以查看“请求”而不是“用户”时,此问题就开始出现了。
以下是我用来更新列表的方法:
private void updateList() {
reference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
result.add(dataSnapshot.getValue(RequestModel.class));
adapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
RequestModel model = dataSnapshot.getValue(RequestModel.class);
int index = getItemIndex(model);
result.set(index, model);
adapter.notifyItemChanged(index);
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
RequestModel model = dataSnapshot.getValue(RequestModel.class);
int index = getItemIndex(model);
result.remove(index);
adapter.notifyItemRemoved(index);
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
这是索引方法:
private int getItemIndex(RequestModel request) {
int index = -1;
for (int i = 0; i < result.size(); i++) {
if (result.get(i).key.equals(request.key)) {
index = i;
break;
}
}
return index;
}
这是我的模特:
public class RequestModel {
String subject, time, name, key;
public RequestModel() {
}
public RequestModel(String subject, String time, String name, String key) {
this.subject = subject;
this.time = time;
this.name = name;
this.key = key;
}
}
修改
onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
auth = FirebaseAuth.getInstance();
String userID = auth.getCurrentUser().getUid();
reference = FirebaseDatabase.getInstance().getReference().child("users").child(userID).child("requests");
result = new ArrayList<>();
recyclerView = (RecyclerView) findViewById(R.id.request_list);
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(llm);
adapter = new RequestAdapter(result);
recyclerView.setAdapter(adapter);
updateList();
更新列表指向@Chan Teck Wei添加的方法。
这是请求的适配器:
private List<RequestModel> list;
public RequestAdapter(List<RequestModel> list) {
this.list = list;
}
@Override
public RequestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new RequestViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_items, parent, false));
}
@Override
public void onBindViewHolder(final RequestViewHolder holder, int position) {
RequestModel request = list.get(position);
holder.requestSubject.setText(request.subject);
holder.requestTime.setText(request.time);
holder.requestName.setText(request.name);
holder.itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
contextMenu.add(holder.getAdapterPosition(), 0, 0, "Chat");
contextMenu.add(holder.getAdapterPosition(), 1, 0, "Report");
}
});
}
@Override
public int getItemCount() {
return list.size();
}
class RequestViewHolder extends RecyclerView.ViewHolder {
TextView requestSubject, requestTime, requestName;
public RequestViewHolder(View itemView) {
super(itemView);
requestSubject = (TextView) itemView.findViewById(R.id.request_subject);
requestTime = (TextView) itemView.findViewById(R.id.request_time);
requestName = (TextView) itemView.findViewById(R.id.request_name);
}
}
答案 0 :(得分:2)
假设您的reference
指向用户/密钥/请求。首先,您将稍微修改一下RequestModel类。
public class RequestModel {
String subject, time, name, key;
private String mKey;
public RequestModel() {
}
public RequestModel(String subject, String time, String name, String key) {
this.subject = subject;
this.time = time;
this.name = name;
this.key = key;
}
public void setKey(String key) {
mKey = key;
}
public String getKey() {
return mKey;
}
}
setKey()
用于设置RequestModel对象,其中包含从数据库中获取的唯一键。然后getKey()
将用于标识对象的实际密钥。它对编辑操作很有用。
ChildEventListener listener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
RequestModel request = dataSnapshot.getValue(RequestModel.class);
request.setKey(dataSnapshot.getKey());
result.add(request);
adapter.notifyItemInserted(result.size());
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
RequestModel request = dataSnapshot.getValue(RequestModel.class);
request.setKey(dataSnapshot.getKey());
for (int i = 0; i < result.size(); i++) {
if (result.get(i).getKey().equals(request.getKey())) {
result.set(i, request);
adapter.notifyItemChanged(i);
break;
}
}
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
RequestModel request = dataSnapshot.getValue(RequestModel.class);
request.setKey(dataSnapshot.getKey());
for (int i = 0; i < result.size(); i++) {
if (result.get(i).getKey().equals(request.getKey())) {
result.remove(i);
adapter.notifyItemRemoved(i);
break;
}
}
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
就个人而言,此实现优于在notifyDataSetChanged()
方法中使用onChildAdded()
。而且,这部动画很有吸引力。