为啥 firebase recyclerview 无法正常工作?

Posted

技术标签:

【中文标题】为啥 firebase recyclerview 无法正常工作?【英文标题】:Why firebase recyclerview is not working correctly?为什么 firebase recyclerview 无法正常工作? 【发布时间】:2021-09-03 08:14:11 【问题描述】:

我尝试在单击每个视频时打开它们,但我得到的只是第二个视频(有时是第一个视频)。例如,当我点击“适合小型企业的 16 个最佳视频创意”时,我希望它打开该特定视频。但我得到的是“这个微型相机可以从错误的角度展示世界。我认为问题的发生是因为 UserHomeVideoAdapter 中的 for 循环内部查询。

UserHomeVideoAdapter.java:

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

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

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

Video video;

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 = documentSnapshot.toObject(Video.class);

                    Log.d("Data", documentSnapshot.getId() + " => " + documentSnapshot.getData());

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

                if (task.getResult().size() != 0) 
                    Glide.with(context).load(model.getUserImageUrl()).into(holder.userProfileImage);
                    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.videoContainer.setOnClickListener(v -> 
        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", videoId);
        intent.putExtra("videoPublisherFullName", model.getUserFullName());
        intent.putExtra("videoPublisherId", publisherId);
        context.startActivity(intent);
    );



@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 videoContainer, mainContainerVideo;
    CircleImageView userProfileImage;
    TextView videoTitle;
    ImageView videoImageView;

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


我记录了在 for 循环中分配的 videoId。有时它会按“1”的顺序返回 id; “2”,有时它会像这样“2”返回; “1”。当它按此顺序返回“1”时;即使我单击第一个视频并且当它像这样“2”返回时,“2”单击也会打开第二个视频;即使我点击第二个视频,“1”点击也会打开第一个视频。

如果您需要其他代码来解决问题,请询问,我会尽快提供。任何帮助表示赞赏。谢谢

【问题讨论】:

请注意,bindViewHolder() 应该只适用于您的回收站视图中的单张卡。如果每张卡都与一个视频相关联,那么您需要将查询移到 bindViewHolder() 之外,甚至可能完全移到适配器之外。 【参考方案1】:

简短的回答是onBindViewHolder() 试图做的太多了。来自the documentation:

由 RecyclerView 调用,在指定位置显示数据。此方法应更新 ViewHolder#itemView 的内容以反映给定位置的项目。

也就是说,onBindViewHolder()只负责RecyclerView中的一项。但是,您正在尝试获取列表中每个元素的所有数据。相反,您应该获取适配器外部的数据并将其作为参数传递。然后onBindViewHolder() 应该更新 RecyclerView 内视图的 UI 元素以显示您想要单个项目的任何内容。

Google has a great example CustomerAdapter.首先,构造函数获取将要显示的数据列表:

    public CustomAdapter(String[] dataSet) 
        mDataSet = dataSet;
    

那么onbindViewHolder()只负责设置RecyclerView中单个item的UI显示什么:

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) 
        Log.d(TAG, "Element " + position + " set.");

        // Get element from your dataset at this position and replace the contents of the view
        // with that element
        viewHolder.getTextView().setText(mDataSet[position]);
    

它不会尝试获取数据或循环列表或其他任何内容。所有这些都是别人的责任。

【讨论】:

感谢您的回答!您能否提供代码,以便我了解如何实施您的解决方案。即使是一个例子也会很有帮助 @RajabMamedli Google's RecyclerView guide 有详细信息和示例应用的链接。 谢谢先生,这真的很有帮助。我会接受你的回答

以上是关于为啥 firebase recyclerview 无法正常工作?的主要内容,如果未能解决你的问题,请参考以下文章

Firebase:Recyclerview 没有附加适配器,跳过布局

Firebase:Recyclerview 没有附加适配器,跳过布局

每次firebase实时数据库数据集时,RecyclerView都会重新加载

Recyclerview 不会从 firebase 检索数据

Recyclerview 未显示来自 Firebase Kotlin 的数据

无法从firebase实时数据库检索数据到recyclerview [重复]