【问题标题】:Recycler View data is duplicated after doing swipeToRefresh multiple times多次滑动刷新后 Recyclerview 数据重复
【发布时间】:2019-10-22 21:05:49
【问题描述】:

我在RecyclerView 中显示Firebase 数据,它工作正常。

我还实现了SwipeRefreshLayout,当用户滑动它时,它会从Firebase 获取最新数据。但是,每当我多次滑动它时,它都会显示重复的值,尽管我正在清除 ArrayList 并且我正在使用 `swipeRefresh.setEnabled(true)``

这里我正在执行SwipeRefreshLayout:

swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                getData();

                if (swipeRefresh.isEnabled())
                    swipeRefresh.setEnabled(false);

            }
        });

这是我的getData() 函数:

    public void getData() {
        pd.setTitle("Loading Data");
        pd.setMessage("Please Wait...");
        pd.setCancelable(false);
        pd.show();

        infoList = new ArrayList<>();
        distributorList = new ArrayList<>();

        infoList.clear();
        distributorList.clear();

        countChilds = 0;
        counter = 0;
        final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
        final DatabaseReference hotelRef = rootRef.child("Orders");
        hotelRef.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                final String key = String.valueOf(dataSnapshot.getKey());
                final String hotelName = String.valueOf(dataSnapshot.child("hotelName").getValue());
                final String location = String.valueOf(dataSnapshot.child("location").getValue());
                final String quantity = String.valueOf(dataSnapshot.child("quantity").getValue());
                final String time = String.valueOf(dataSnapshot.child("time").getValue());

                final DatabaseReference progressRef = rootRef.child("Progress").child(key);
                ValueEventListener eventListener = new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot.exists()) {
                            shipment = String.valueOf(dataSnapshot.child("shipment").getValue());
                            firstMile = String.valueOf(dataSnapshot.child("firstMile").getValue());
                            distributor = String.valueOf(dataSnapshot.child("distributor").getValue());
                        }
                        if (shipment.equals("1") && firstMile.equals("2") && !distributor.equals("2")) {
                            counter++;
                            Information information = new Information(key, hotelName, location, quantity, time);
                            infoList.add(information);
                            distributorList.add(distributor);

                            try {
                                adapter = new DistributorItemAdapter(infoList, distributorList, getContext(), DistributorListFragment.this);
                                recyclerView.setAdapter(adapter);
                            } catch (IndexOutOfBoundsException e) {
                                e.printStackTrace();
                            } catch (NullPointerException e) {
                                Toast.makeText(getContext(), "No more Orders", Toast.LENGTH_SHORT).show();
                                e.printStackTrace();
                            }

                        } else {
                            shipment = "";
                            distributor = "";
                            firstMile = "";
                        }

                        if (counter == 0) {
                            emptyView.setVisibility(View.VISIBLE);
                            recyclerView.setAdapter(null);
                        } else
                            emptyView.setVisibility(View.GONE);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        Log.d("Database Error", databaseError.getMessage());
                    }
                };
                progressRef.addListenerForSingleValueEvent(eventListener);

                countChilds++;
                if (countChilds >= dataSnapshot.getChildrenCount()) {
                    if (pd.isShowing())
                        pd.dismiss();
                    if (!swipeRefresh.isEnabled())
                        swipeRefresh.setEnabled(true);
                    swipeRefresh.setRefreshing(false);

                }
            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }

        });
    }

【问题讨论】:

  • 重新设置适配器不是个好主意。相反,只需分配获得的数据并调用 notifyDatasetChanged() 方法来通知您的数据已更改。如果您确定没有重复发生,则设置 null 以在 onBindViewHolder 中释放 viewholder 的数据。
  • 在哪里调用 notifyDatasetChanged()?
  • 那个方法属于RecyclerView.Adapter。这意味着您可以调用 yourAdapterInstance.notifyDataSetChanged()。请参考developer.android.com/reference/android/support/v7/widget/…
  • 如果 firebase 是实时的,为什么需要滑动刷新?
  • @cutiko 因为当添加新数据时,我想显示未自动显示的最新数据。

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


【解决方案1】:

您应该初始化您的adapter,在此您将您的recylerviewset adapter 初始化为recylcerView,如下所示。

//recyclerView = findViewById.....

infoList = new ArrayList<>();
distributorList = new ArrayList<>();
adapter = new DistributorItemAdapter(infoList, distributorList, getContext(), DistributorListFragment.this);
recyclerView.setAdapter(adapter);

现在修改您的getData(),如下所示。

public void getData() {
  pd.setTitle("Loading Data");
  pd.setMessage("Please Wait...");
  pd.setCancelable(false);
  pd.show();

  infoList.clear();
  distributorList.clear();

  countChilds = 0;
  counter = 0;
  final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
  final DatabaseReference hotelRef = rootRef.child("Orders");
  hotelRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            final String key = String.valueOf(dataSnapshot.getKey());
            final String hotelName = String.valueOf(dataSnapshot.child("hotelName").getValue());
            final String location = String.valueOf(dataSnapshot.child("location").getValue());
            final String quantity = String.valueOf(dataSnapshot.child("quantity").getValue());
            final String time = String.valueOf(dataSnapshot.child("time").getValue());

           final DatabaseReference progressRef = rootRef.child("Progress").child(key);
           ValueEventListener eventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                   if (dataSnapshot.exists()) {
                       shipment = String.valueOf(dataSnapshot.child("shipment").getValue());
                       firstMile = String.valueOf(dataSnapshot.child("firstMile").getValue());
                       distributor = String.valueOf(dataSnapshot.child("distributor").getValue());
                   }
                   if (shipment.equals("1") && firstMile.equals("2") && !distributor.equals("2")) {
                        counter++;
                        Information information = new Information(key, hotelName, location, quantity, time);
                         infoList.add(information);
                         distributorList.add(distributor);

                         // notify your adapter that data set is changed
                         adapter.notifyDatasetChanged();

                        } else {
                            shipment = "";
                            distributor = "";
                            firstMile = "";
                        }

                        if (counter == 0) {
                            emptyView.setVisibility(View.VISIBLE);
                            recyclerView.setAdapter(null);
                        } else
                            emptyView.setVisibility(View.GONE);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        Log.d("Database Error", databaseError.getMessage());
                    }
                };
                progressRef.addListenerForSingleValueEvent(eventListener);

                countChilds++;
                if (countChilds >= dataSnapshot.getChildrenCount()) {
                    if (pd.isShowing())
                        pd.dismiss();
                    if (!swipeRefresh.isEnabled())
                        swipeRefresh.setEnabled(true);
                    swipeRefresh.setRefreshing(false);

                }
            }

           //....

    });
}

【讨论】:

  • adapter.notifyDatasetChanged();不起作用,它在 RecyclerView 中没有显示任何内容
  • 这意味着我的回收站视图中没有显示数据
  • 它应该可以工作。如果您以前的(上述问题)代码有效。请仔细检查您是否遗漏了什么。
  • 我上面的代码正在工作并且正在显示数据。并且工作正常,但现在什么也没显示。我已经使用 Log 来检查数据是否来自 firebase,它是完美的,除了没有显示任何数据的适配器
  • 您能提出其他解决方案吗?
猜你喜欢
  • 1970-01-01
  • 2017-02-09
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 2019-10-07
  • 2021-12-11
  • 1970-01-01
相关资源
最近更新 更多