为啥 recyclerview 返回错误的项目?

Posted

技术标签:

【中文标题】为啥 recyclerview 返回错误的项目?【英文标题】:Why recyclerview returns wrong item?为什么 recyclerview 返回错误的项目? 【发布时间】:2021-09-04 01:23:32 【问题描述】:

我尝试在单击 itemview 时打开视频。有时它可以正常工作,但有时当我单击第一个视频时它会打开第二个视频,反之亦然。我试图实现的是当我点击第一个 recyclerview 项目时打开第一个视频等等。

UserHomeVideoAdapter.java:

public class UserHomeVideoAdapter extends FirestoreRecyclerAdapter<FollowList, UserHomeVideoAdapter.UserVideoHolder> 

    Context context;
    final FirebaseFirestore db = FirebaseFirestore.getInstance();

    String thumbUrl, videoTitle, videoUrl, videoDesc, videoId, publisherId;

    ArrayList<String> videoIdArrayList = new ArrayList<>();

    public UserHomeVideoAdapter(@NonNull @NotNull FirestoreRecyclerOptions<FollowList> options, Context context) 
        super(options);
        this.context = context;
    

    @Override
    protected void onBindViewHolder(@NonNull @NotNull UserVideoHolder holder, int position, @NonNull @NotNull FollowList model) 

        Query query = db.collection("Videos").whereEqualTo("publisherId", model.getUserId());

        query.get().addOnCompleteListener(task ->  
            if (task.isSuccessful()) 
                if (task.getResult() != null) 
                    for (QueryDocumentSnapshot documentSnapshot : task.getResult()) 
                        Video video = documentSnapshot.toObject(Video.class);

                        thumbUrl = video.getThumbUrl();
                        videoTitle = video.getVideoTitle();
                        videoUrl = video.getVideoUrl();
                        videoDesc = video.getVideoDesc();
                        videoId = video.getVideoId();
                        publisherId = video.getPublisherId();

                        videoIdArrayList.add(videoId);
                    

                    if (task.getResult().size() > 0) 
                        db.collection("Users").document(model.getUserId()).get().addOnSuccessListener(documentSnapshot -> 
                            if (documentSnapshot != null) 
                                final User user = documentSnapshot.toObject(User.class);

                                if (user != null) 
                                    if (user.getUserImageUrl() == null) 
                                        holder.userProfileImage.setImageResource(R.drawable.ic_launcher_background);
                                     else 
                                        Glide.with(context).load(Uri.parse(user.getUserImageUrl())).into(holder.userProfileImage);
                                    
                                
                            
                        ).addOnFailureListener(e -> Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show());

                        Glide.with(context).load(thumbUrl).into(holder.videoImageView);
                        holder.videoTitle.setText(videoTitle);
                        holder.mainContainerVideo.setVisibility(View.VISIBLE);
                     else if (task.getResult().size() == 0) 
                        holder.mainContainerVideo.getLayoutParams().height = 0;
                        holder.mainContainerVideo.getLayoutParams().width = 0;
                    
                
             else 
                Toast.makeText(context, String.valueOf(task.getException()), Toast.LENGTH_SHORT).show();
            
        ).addOnFailureListener(e -> Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show());

        holder.itemView.setOnClickListener(view -> 
            Intent intent = new Intent(context, VideoActivity.class);
            intent.putExtra("videoPublisherUserName", model.getUserName());
            intent.putExtra("thumbUrl", thumbUrl);
            intent.putExtra("videoPublisherEmail", model.getUserEmail());
            intent.putExtra("videoUrl", videoUrl);
            intent.putExtra("videoId", videoIdArrayList.get(position));
            intent.putExtra("videoPublisherFullName", model.getUserFullName());
            intent.putExtra("videoPublisherId", publisherId);
            context.startActivity(intent);

            Log.d("Bax", videoIdArrayList.get(position));
        );
    

    @NonNull
    @NotNull
    @Override
    public UserVideoHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) 
        View v = LayoutInflater.from(context).inflate(R.layout.video_cell, parent, false);
        return new UserVideoHolder(v);
    

    public static class UserVideoHolder extends RecyclerView.ViewHolder 
        RelativeLayout mainContainerVideo;
        CircleImageView userProfileImage;
        TextView videoTitle;
        ImageView videoImageView;

        public UserVideoHolder(@NonNull @NotNull View itemView) 
            super(itemView);
            mainContainerVideo = itemView.findViewById(R.id.mainContainerVideo);
            userProfileImage = itemView.findViewById(R.id.userProfileImage);
            videoTitle = itemView.findViewById(R.id.videoTitle);
            videoImageView = itemView.findViewById(R.id.videoImageView);
        
    

我不明白我的代码存在的问题,因此感谢您提供任何帮助。谢谢

【问题讨论】:

您的 recyclerview 目前有多少个视频? @skafle 现在是 2,但它可以随着用户将来上传而改变 【参考方案1】:

这里的问题是您的videoIdArrayList.add(videoId) 没有被重置。每次您的 recyclerview 加载时,它都会查询数据库并在 videoIdArrayList 中添加 videoId 并不断添加。

这会弄乱要发送到下一个活动的 videoId。 因此,请清除您的 videoIdArrayList 每次 recyclerview 加载并在此之后添加 Id。

因此,在 firebase 查询中的 for 循环之前,只需清除列表即可。 videoIdArrayList.clear()

应该可以完美运行。

【讨论】:

不幸的是,我按照您的建议做了,但没有得到任何结果。我什至尝试在我的 clicklistener 中清除 arraylist,但又没有结果。 是的...正如@anatoli 建议的那样,您的查询被执行的次数与您的recyclerview 在给定时间持有的项目数一样多。因此,最好将您的查询代码传输到不同的文件,然后在初始化适配器时将列表传递给适配器。【参考方案2】:

onBindViewHolderRecyclerView 中的每个项目执行。一次都没有

Query query = db.collection("Videos").whereEqualTo("publisherId", model.getUserId()); 返回 List,而不是项目。

videoIdArrayList.add(videoId); 可以多次执行第一项。

String thumbUrl, videoTitle, videoUrl, videoDesc, videoId, publisherId; 在 Query 中设置为 onBindViewHolder。再次为RecyclerView 中的每个项目执行onBindViewHolder。一次都没有。

你必须重构你的适配器。

    通过您的适配器执行查询。 目前尚不清楚,哪些物品会收到持有人。 (对我来说。如果你很清楚 -> 跳过这一步) 而不是 holder.videoTitle 在 holder 中创建一个方法(例如 void configView(YourItem item)),并在 holder 中执行与该项目有关的一切。

【讨论】:

以上是关于为啥 recyclerview 返回错误的项目?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 RecyclerView 项目在 GridLayoutManager 中随机移动位置?

为啥 RecyclerView 项目在点击两次后才改变背景颜色?

为啥 notifyItemChanged(position) 不更新 RecyclerView 中的所有项目?

为啥这些随机标记出现在每个 recyclerview 和 viewpager 项目中?

为啥直到在选项卡之间滚动才会显示 recyclerview 项目?

为啥在recyclerview android中滚动后突出显示的项目丢失