【问题标题】:Recyclerview fetch existing data after delete an item from adapter and does not update properly从适配器中删除项目后,Recyclerview 获取现有数据并且未正确更新
【发布时间】:2019-12-06 21:33:55
【问题描述】:

我尝试使用带有 firebase 数据库的自定义适配器在片段中实现好友请求功能。问题是当用户接受或删除某人的请求时,它会从 firebase 中删除,但不会在 RecyclerView 中正确更新。此问题仅发生在运行时。如果我刷新页面,我的问题就会消失。

让我有两个好友请求。如果我删除第二个数据,那么第二个数据将从RecyclerView 消失,但问题是RecyclerView 显示第一个数据加倍。如果我删除第一个数据,那么第一个数据进入第二行,第二个数据进入第一行。

这是我的数据库截图

片段类-

public class NotificationFragment extends Fragment {

private RecyclerView NotificationRecyclerView;
private NotificationAdapter adapter;
private List<Friend> friendList;

public NotificationFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_notification, container, false);

    NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
    NotificationRecyclerView.setHasFixedSize(true);
    LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
    NotificationRecyclerView.setLayoutManager(LayoutManager);
    friendList = new ArrayList<>();
    adapter = new NotificationAdapter(getContext(), friendList);
    NotificationRecyclerView.setAdapter(adapter);

    readAllNotification();

    return view;
}

private void readAllNotification() {

    final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();

    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                Friend friend = snapshot.getValue(Friend.class);
                if (firebaseUser.getUid().equals(friend.getReceiverID())) {
                    friendList.add(friend);
                }
            }

            Collections.reverse(friendList);
            adapter.notifyDataSetChanged();
        }

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

        }
    });
}

}

自定义适配器 -

public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationViewHolder> {

private Context context;
private List<Friend> friendList;

public NotificationAdapter(Context context, List<Friend> friendList) {
    this.context = context;
    this.friendList = friendList;
}

@NonNull
@Override
public NotificationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(context).inflate(R.layout.single_notification_item, parent, false);
    return new NotificationAdapter.NotificationViewHolder(view);

}

@Override
public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) {

    final Friend friend = friendList.get(position);

    getUserInfo(holder.profileImage, holder.NotificationUserName, friend.getSenderID());

    holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FirebaseDatabase.getInstance().getReference("FriendRequest")
                    .child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    removeItem(position);
                    Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
                }
            });
        }
    });

}

public void removeItem(int position) {
    friendList.remove(position);
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return friendList.size();
}

private void getUserInfo(final CircleImageView prfileImage, final TextView NotificationUserName, String senderID) {

    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(senderID);
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Users users = dataSnapshot.getValue(Users.class);

            NotificationUserName.setText(users.getUserName());
            Picasso.with(context).load(users.getImageUrl()).into(prfileImage);
        }

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

        }
    });
}

public class NotificationViewHolder extends RecyclerView.ViewHolder {

    private TextView NotificationUserName;
    private Button cancelRequestButton;
    private CircleImageView profileImage;

    public NotificationViewHolder(@NonNull View itemView) {
        super(itemView);

        NotificationUserName = itemView.findViewById(R.id.NotificationUserName);
        cancelRequestButton = itemView.findViewById(R.id.cancelRequestBtn);
        profileImage = itemView.findViewById(R.id.profileImage);
    }
}

}

我的 APP 问题截图 - 让我有两个要求 1)如果我删除第二个数据第一个数据显示双打:

2)如果我删除第一个数据,第一个数据进入第二行,第二个数据进入第一行:

【问题讨论】:

    标签: android android-studio android-recyclerview custom-adapter


    【解决方案1】:

    替换

     removeItem(position);
    

     removeItem(holder.getAdapterPosition());
    

    【讨论】:

    • 您是否尝试过对`final Friendfriend =friendList.get(position); 应用相同的更改? `,将位置替换为 holder.getAdapterPosition(),通常您从 OnBindViewHolder() 获得的位置是指适配器数据集中项目的位置,从我在文档中读到的内容
    • 是的,我也试了,但问题没有解决,先生
    【解决方案2】:

    您在onCreateView 中初始化您的recyclerViewadapter,这是不合适的。您必须重写方法onViewCreated,然后初始化您的recyclerView 和adapter。像这样尝试

    public class NotificationFragment extends Fragment {
    
    private RecyclerView NotificationRecyclerView;
    private NotificationAdapter adapter;
    private List<Friend> friendList;
    
    public NotificationFragment() {
    // Required empty public constructor
    }
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_notification, container, false);
    
    
    return view;
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    
      NotificationRecyclerView = view.findViewById(R.id.NotificationRecyclerView);
    NotificationRecyclerView.setHasFixedSize(true);
    LinearLayoutManager LayoutManager = new LinearLayoutManager(getContext());
    NotificationRecyclerView.setLayoutManager(LayoutManager);
    friendList = new ArrayList<>();
    adapter = new NotificationAdapter(getContext(), friendList);
    NotificationRecyclerView.setAdapter(adapter);
    
    readAllNotification();
    
    }
    
    private void readAllNotification() {
    
    final FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
    
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("FriendRequest");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                Friend friend = snapshot.getValue(Friend.class);
                if (firebaseUser.getUid().equals(friend.getReceiverID())) {
                    friendList.add(friend);
                }
            }
    
            Collections.reverse(friendList);
            adapter.notifyDataSetChanged();
        }
    
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
    
        }
    });
    }
    

    好的,我刚刚注意到您使用 holder.getAdapterPosition()removeItem 方法中传递了一个参数,这导致了您的问题。尝试传递由 public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) 提供的位置。所以基本错误是当您在onBindViewHolder 你不需要使用holder.getAdapterPosition() 因为onBindViewHolder 已经给了你职位

    在您的 removeItem 方法中使用 notifyDataSetChanged 而不是 notifyItemRemoved(position) 试试这样

        @Override
    public void onBindViewHolder(@NonNull final NotificationViewHolder holder, final int position) {
      final Friend friend = friendList.get(position);
      holder.cancelRequestButton.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            FirebaseDatabase.getInstance().getReference("FriendRequest").child(friend.getRequestID()).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    removeItem(position);
                    Toast.makeText(context, "removed", Toast.LENGTH_SHORT).show();
                }
            });
        }
    });
    }
      public void removeItem(int position) {
    friendList.remove(position);
    notifyDataSetChanged();
    }
    

    【讨论】:

    • 使用 notifyDataSetChanged 方法它也不起作用先生:(。同样的问题发生
    • 我刚刚更新了我的答案,请检查一下。希望它能解决您的问题
    • 您好,先生,我已经尝试使用 viewholder 类中的 removeItem(position) 方法,但出现了同样的问题。这个问题只发生在运行时。如果我单击通知图标并再次进入请求 tabLayout,则问题会自动消失。如果我只有一件物品,那么就不会发生任何问题。
    • 我不知道您尝试了哪些方法,但我再次更新了我的答案,您是否像这样尝试过,就像我在答案中写的那样?
    • 是的,我尝试完全相同的东西先生:(
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 2021-01-24
    • 2020-05-06
    • 2017-12-15
    • 2020-07-27
    • 1970-01-01
    • 2018-08-08
    相关资源
    最近更新 更多