似乎发生的情况是,如果 Firebase 中的子项发生更改,recyclerview 会将最上面的项目替换为更改后的值。
例如,如果我将“微积分”更改为“化学”,它会将条目“生物学,约翰,晚上 7 点”替换为“化学,约翰,晚上 8 点”(当然仅在回收 View 本身中)。仅在使用 recreate() 重新启动 Activity 时才会更正 recyclerview。当 onChildRemoved 时,也会出现同样的问题,因为最上面的条目被删除(在回收器 View 中),而不是实际从数据库中删除的条目。
当我更改数据库引用以查看“请求”而不是“用户”时,此问题开始出现。
这是我用来更新列表的方法:
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);
}
}
最佳答案
假设您的引用
指向users/key/requests。首先,您将稍微修改一下 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()
将用于识别对象的实际 key 。这对于编辑操作很有用。
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) {
}
});
就个人而言,此实现比在方法 onChildAdded()
中使用 notifyDataSetChanged()
更好。而且,动画很养眼。
关于Android Firebase Recyclerview 更改错误项目的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48876703/