我在使用recyclerview删除元素时遇到问题。如果我按顺序删除它们,它工作正常,但如果我以随机顺序删除它们,它不会考虑RecyclerView索引。
活动
@Override
public void onStart() {
super.onStart();
try {
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mListView.setLayoutManager(mLinearLayoutManager);
mMessagesListAdapter = new ChatAdapter(mFirebaseRef.limitToLast(50), this, mId, mUser);
mListView.setAdapter(mMessagesListAdapter);
mMessagesListAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
mListView.scrollToPosition(mMessagesListAdapter.getItemCount() - 1);
}
});
mListView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mLinearLayoutManager.findLastCompletelyVisibleItemPosition() + 3 < mMessagesListAdapter.getItemCount()) {
if (!mBtnBottom.isShown()) mBtnBottom.setVisibility(View.VISIBLE);
} else if (mBtnBottom.isShown()) {
mBtnBottom.setVisibility(View.GONE);
}
}
});
} catch (Exception e) {
Log.e(TAG_CLASS, "Bad adapter:" + e.toString());
}
}
FirebaseListAdapter
public abstract class FirebaseListAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Query mRef;
private Class<T> mModelClass;
private List<T> mModels;
private Map<String, T> mModelKeys;
private List<String> mKeys;
private ChildEventListener mListener;
private boolean mSearchingFlag ;
/**
* @param mRef The Firebase location to watch for data changes. Can also be a slice of a location, using some
* combination of <code>limit()</code>, <code>startAt()</code>, and <code>endAt()</code>,
* @param mModelClass Firebase will marshall the data at a location into an instance of a class that you provide
*/
public FirebaseListAdapter(Query mRef, final Class<T> mModelClass) {
this(mRef, mModelClass,false);
}
public FirebaseListAdapter(Query mRef, final Class<T> mModelClass,final boolean keepsynced) {
this.mSearchingFlag=mSearchingFlag;
this.mRef = mRef;
this.mModelClass = mModelClass;
mModels = new ArrayList<T>();
mModelKeys = new HashMap<String, T>();
mKeys = new ArrayList<String>();
mRef.keepSynced(true);
// Look for all child events. We will then map them to our own internal ArrayList, which backs ListView
mListener = this.mRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
T model;
String key;
try {
if(dataSnapshot.hasChild("_source")){
model = dataSnapshot.child("_source").getValue(FirebaseListAdapter.this.mModelClass);
Log.d("Snapshot:",dataSnapshot.toString());
}else {
model = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
}
key = dataSnapshot.hasChild("_id")? dataSnapshot.child("_id").getValue().toString():dataSnapshot.getKey();
mModelKeys.put(key, model);
// Insert into the correct location, based on previousChildName
if (previousChildName == null) {
mModels.add(0, model);
mKeys.add(0, key);
} else {
T previousModel = mModelKeys.get(previousChildName);
int previousIndex = mModels.indexOf(previousModel);
int nextIndex = previousIndex + 1;
if (nextIndex == mModels.size()) {
mModels.add(model);
mKeys.add(key);
} else {
mModels.add(nextIndex, model);
mKeys.add(nextIndex, key);
}
}
}catch(Exception e){
key = dataSnapshot.hasChild("_id")? dataSnapshot.child("_id").getValue().toString():dataSnapshot.getKey();
Log.e("FirebaseListAdapter",key+" has a bad model: "+dataSnapshot.toString());
}finally {
notifyDataSetChanged();
}
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
// One of the mModels changed. Replace it in our list and name mapping
String modelName = dataSnapshot.hasChild("_id")? dataSnapshot.child("_id").getValue().toString():dataSnapshot.getKey();
Log.d("change",s+dataSnapshot.getKey());
T oldModel = mModelKeys.get(modelName);
T newModel;
if(dataSnapshot.hasChild("_source")){
newModel = dataSnapshot.child("_source").getValue(FirebaseListAdapter.this.mModelClass);
}else {
newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
}
int index = mModels.indexOf(oldModel);
//Return if model is no longer found
if(index == -1) return;
mModels.set(index, newModel);
mModelKeys.put(modelName, newModel);
mKeys.set(index, modelName);
notifyDataSetChanged();
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
if(!dataSnapshot.hasChild("_id")){
Log.e("childReMoved","snap:"+dataSnapshot.getKey());
String modelName = dataSnapshot.getKey();
// A model was removed from <></>he list. Remove it from our list and the name mapping
T oldModel = mModelKeys.get(modelName);
mModels.remove(oldModel);
mKeys.remove(oldModel);
mModelKeys.remove(modelName);
notifyDataSetChanged();
}
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
if(dataSnapshot.hasChild("_id")){
return;
}
Log.e("childMoved","snap:"+dataSnapshot.getKey());
// A model changed position in the list. Update our list accordingly
String modelName = dataSnapshot.hasChild("_id")? dataSnapshot.child("_id").getValue().toString():dataSnapshot.getKey();
T oldModel = mModelKeys.get(modelName);
T newModel;
if(dataSnapshot.hasChild("_source")){
newModel = dataSnapshot.child("_source").getValue(FirebaseListAdapter.this.mModelClass);
}else {
newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass);
}
int index = mModels.indexOf(oldModel);
//Return if old model is no longer found
if(index==-1)return;
mModels.remove(index);
mKeys.remove(index);
if (previousChildName == null) {
mModels.add(0, newModel);
mKeys.add(0, modelName);
} else {
T previousModel = mModelKeys.get(previousChildName);
int previousIndex = mModels.indexOf(previousModel);
int nextIndex = previousIndex + 1;
if (nextIndex == mModels.size()) {
mModels.add(newModel);
mKeys.add(modelName);
} else {
mModels.add(nextIndex, newModel);
mKeys.add(nextIndex, modelName);
}
}
notifyDataSetChanged();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.e("FirebaseListAdapter", "Listen was cancelled, no more updates will occur");
}
});
}
public void cleanup() {
// We're being destroyed, let go of our mListener and forget about all of the mModels
Log.d("FirebaseListAdapter","cleanup()");
mRef.removeEventListener(mListener);
mModels.clear();
mModelKeys.clear();
}
@Override
public int getItemCount() {
return mModels.size();
}
@Override
public long getItemId(int i) {
return i;
}
public T getItem(int i){
return mModels.get(i);
}
public String getItemKey(int i){
return mKeys.get(i);
}
}
删除更新的代码是
FirebaseDatabase.getInstance().getReference("updates/" + mStoryKey + "/" + mUpdateKey).removeValue();
记录结果:
I/EditPostDialogFragment: **query**:
updates/-K_ac4rB2KNAKIPC9zhb/-KaB1XHf7AdbJ2QvXrmv
I/EditPostDialogFragment: **Deleting** :
firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/-KaB1XHf7AdbJ2QvXrmv
E/childReMoved: snap:-KaB1XHf7AdbJ2QvXrmv
记录结果:
I/EditPostDialogFragment: **query**:
updates/-K_ac4rB2KNAKIPC9zhb/-KaB1WLk-FotMek51d3l
I/EditPostDialogFragment: **Deleting** :
firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/**-KaB1WLk-FotMek51d3l**
E/childReMoved: snap:**-KaB1WLk-FotMek51d3l**
观察以下步骤如何尝试删除与之前相同的ID。
I/EditPostDialogFragment: **query**:
updates/-K_ac4rB2KNAKIPC9zhb/-KaB1WLk-FotMek51d3l
I/EditPostDialogFragment: **Deleting** :
firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/**-KaB1WLk-FotMek51d3l**
答案 0 :(得分:0)
onChildRemoved覆盖尝试使用item作为键从mKeys中删除元素,使用modelname作为删除键应解决问题。
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
if(!dataSnapshot.hasChild("_id")){
Log.e("childReMoved","snap:"+dataSnapshot.getKey());
String modelName = dataSnapshot.getKey();
// A model was removed from <></>he list. Remove it from our list and the name mapping
T oldModel = mModelKeys.get(modelName);
mModels.remove(oldModel);
mKeys.remove(modelName);
mModelKeys.remove(modelName);
notifyDataSetChanged();
}
}