【问题标题】:Prevent entire RecyclerView from refreshing, add only new item防止整个 RecyclerView 刷新,只添加新项目
【发布时间】:2018-12-23 09:41:24
【问题描述】:

我有嵌套的侦听器来检索数据:首先我从数据数据库中检索数据,然后,我得到一个拥有这些数据的用户列表,并将当前用户的列表保存在一个 ArrayList 中,这将是RecyclerView 的数据集。然后,我需要从用户数据库(他们的图像 ID)中获取有关这些用户的一些信息,因此我从第一个 onDataChange 调用中再次调用用户数据库(因为它是异步的,我需要嵌套它们)。但是当我用新项目更新 ArrayList 时,或者每次数据库发生变化时,RecyclerView 都会“刷新”。这是代码:

**我认为原因是每次调用onDataChange 时我都会调用新适配器。那么如何查看之前是否设置了适配器,如果设置了就不要再设置呢?

DatabaseReference rootReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference dataReference = rootReference.child("data");
ValueEventListener dataListener= new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

            final ArrayList<String> foundUsers = new ArrayList<>();

            for (DataSnapshot dSnapshot : dataSnapshot.getChildren()) {
                String userId= dSnapshot.getKey();
                for(DataSnapshot ds : dSnapshot.getChildren()) {    
                    if (userIsFound()){
                        foundUsers.add(userId);
                    }
                }
            }

            mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
            mRecyclerView.setHasFixedSize(true);

            // use a linear layout manager
            mLayoutManager = new LinearLayoutManager(getActivity());
            mRecyclerView.setLayoutManager(mLayoutManager);
            myDataset = new ArrayList<User>();
            mAdapter = new MyAdapter(myDataset);                
            mRecyclerView.setAdapter(mAdapter);


            DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
            DatabaseReference imageIdRef= rootRef.child("users");
            ValueEventListener eventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for(DataSnapshot ds : dataSnapshot.getChildren()) {
                        String currentUserId = ds.getKey();
                        if (foundUsers.contains(currentUserId )) {
                            if (ds.child("imageUrl").getValue() != null) {
                                String imageUrl = ds.child("imageUrl").getValue().toString();
                                myDataset.add(new User(currentUserId, imageUrl));
                            }
                        }
                        mAdapter.notifyDataSetChanged();                           

                    }
                    foundUsers.clear();
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {}
            };
            imageIdRef.addValueEventListener(eventListener);

        }


        @Override
        public void onCancelled(DatabaseError databaseError) {}
    };

    dataReference.addValueEventListener(dataListener);

【问题讨论】:

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


    【解决方案1】:

    您需要在 User 类中覆盖 equals 方法,以便 contains 正常工作:

    @Override
        public boolean equals(@Nullable Object obj) {
            if( obj instanceof User){
                User = (User) obj;
                return this.getCurrentUserId().equals(obj.getCurrentUserId());
            }else{
                return false;
            }
        }
    

    并使用:

    mAdapter.notifyItemInserted(myDataset.size() - 1);
    

    【讨论】:

    • 你确定是这个问题吗?不是因为每次调用onDataChange 时我都会调用创建新适配器吗?
    • 您也需要将适配器初始化移到 Firebase 逻辑之外
    • 好的,我把它移走了,但现在问题是由new User 语句引起的——它多次添加了同一用户的新实例。如何防止这种情况?您的代码不起作用
    • 我认为我必须使用 HashMap 而不是 ArrayList 来防止重复,不是吗?
    【解决方案2】:

    试试

    mAdapter.notifyItemInserted(position);
    

    或者试试下面,它会通知最后添加的位置

    mAdapter.notifyItemInserted((myDataset.size())-1);
    

    【讨论】:

    • 这不是问题,我认为问题是每次调用数据库时我都设置了新的适配器
    猜你喜欢
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多