从回收器视图中删除元素不会对索引重新排序

时间:2017-01-11 05:55:01

标签: android firebase android-recyclerview firebase-realtime-database

我在使用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();
  1. 记录结果:

    I/EditPostDialogFragment: **query**: 
    updates/-K_ac4rB2KNAKIPC9zhb/-KaB1XHf7AdbJ2QvXrmv
    I/EditPostDialogFragment: **Deleting** : 
    firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/-KaB1XHf7AdbJ2QvXrmv
    
    E/childReMoved: snap:-KaB1XHf7AdbJ2QvXrmv
    
  2. 记录结果:

    I/EditPostDialogFragment: **query**: 
    updates/-K_ac4rB2KNAKIPC9zhb/-KaB1WLk-FotMek51d3l
    I/EditPostDialogFragment: **Deleting** : 
    firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/**-KaB1WLk-FotMek51d3l**
    
    E/childReMoved: snap:**-KaB1WLk-FotMek51d3l**
    
  3. 观察以下步骤如何尝试删除与之前相同的ID。

    I/EditPostDialogFragment: **query**: 
    updates/-K_ac4rB2KNAKIPC9zhb/-KaB1WLk-FotMek51d3l
    I/EditPostDialogFragment: **Deleting** : 
    firebaseio.com/updates/-K_ac4rB2KNAKIPC9zhb/**-KaB1WLk-FotMek51d3l**
    

1 个答案:

答案 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();
            }
        }