如何在RecyclerView中多次展示同一Firebase用户的视频数据
实现方案
核心逻辑:当前代码1个用户数据模型对应1个列表项,要实现单用户展示3个视频条目,最稳妥的方式是先把用户数据展平为「每个视频对应1个列表项」的数据结构,再传给Adapter渲染,改动量小且后续易维护。
步骤1:新增列表专用的视频条目模型
原有ModelClass是和Firebase数据库结构对应的用户模型,不需要修改,新增一个专门给RecyclerView条目使用的模型即可:
public class VideoItem { private final String userName; private final String videoUrl; public VideoItem(String userName, String videoUrl) { this.userName = userName; this.videoUrl = videoUrl; } public String getUserName() { return userName; } public String getVideoUrl() { return videoUrl; } }
步骤2:修改HomeFragment的数据处理逻辑
从Firebase取到原始用户数据后,把每个用户的3个视频拆成独立的VideoItem存入列表,修正原有打乱顺序的逻辑位置:
dRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { ArrayList<VideoItem> displayList = new ArrayList<>(); for (DataSnapshot dataSnapshot : snapshot.getChildren()) { ModelClass user = dataSnapshot.getValue(ModelClass.class); if (user == null) continue; // 非空判断,避免数据库字段缺失导致加载空地址报错 if (!TextUtils.isEmpty(user.getVideo1())) { displayList.add(new VideoItem(user.getName(), user.getVideo1())); } if (!TextUtils.isEmpty(user.getVideo2())) { displayList.add(new VideoItem(user.getName(), user.getVideo2())); } if (!TextUtils.isEmpty(user.getVideo3())) { displayList.add(new VideoItem(user.getName(), user.getVideo3())); } } // 所有条目添加完成后再打乱顺序,不要写在循环内部 Collections.shuffle(displayList); recyclerView.setAdapter(new MyAdapter(requireContext(), displayList)); } @Override public void onCancelled(@NonNull DatabaseError error) { // 这里补充数据库读取失败的兜底逻辑,比如Toast提示 } });
注意:首次给RecyclerView设置Adapter时不需要额外调用notifyDataSetChanged(),setAdapter本身会触发视图刷新,多余调用会造成无意义的性能消耗。
步骤3:修改Adapter适配新的列表数据
把Adapter的数据源换成VideoItem类型,绑定数据时直接取当前条目的视频地址加载即可:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private final Context context; private final ArrayList<VideoItem> videoItemList; public MyAdapter(Context context, ArrayList<VideoItem> videoItemList) { this.context = context; this.videoItemList = videoItemList; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(context).inflate(R.layout.gig_display_layout, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { VideoItem currentItem = videoItemList.get(position); holder.urlEmbeddedView.setURL(currentItem.getVideoUrl(), new URLEmbeddedView.OnLoadURLListener() { @Override public void onLoadURLCompleted(URLEmbeddedData data) { holder.urlEmbeddedView.title(data.getTitle()); holder.urlEmbeddedView.description(data.getDescription()); holder.urlEmbeddedView.host(data.getHost()); holder.urlEmbeddedView.thumbnail(data.getThumbnailURL()); holder.urlEmbeddedView.favor(data.getFavorURL()); } }); // 如果需要在条目上展示对应用户名,调用currentItem.getUserName()即可 } @Override public int getItemCount() { return videoItemList == null ? 0 : videoItemList.size(); } static class MyViewHolder extends RecyclerView.ViewHolder{ URLEmbeddedView urlEmbeddedView; public MyViewHolder(@NonNull View itemView) { super(itemView); urlEmbeddedView = itemView.findViewById(R.id.urlView); } } }
其他说明
- 不推荐通过
getItemCount() 返回 用户数*3、在onBindViewHolder中用position/3算用户索引、position%3判断视频序号的实现方式,这种方式索引计算容易出错,后续如果要支持可变视频数量、多视图类型时改造成本极高。 - 如果后续需要扩展支持每个用户上传任意数量的视频,建议把数据库中的video1/video2/video3固定字段改为视频列表存储,取数时直接遍历视频列表生成VideoItem即可,无需修改Adapter逻辑。
内容的提问来源于stack exchange,提问作者Gum Naam
相关产品推荐
相关产品推荐

