如何在适配器 class 的 RecyclerView 中提供子项的条件可见性?

How to provide conditional visibility of a child-item in a RecyclerView in the Adapter class?

我正在开发一个项目,该项目为每个屏幕实现 2 个视图,一个普通用户视图和一个管理视图。管理员视图比普通用户有更多的权限,比如从数据库中删除某些帖子或用户本身。

因此,如果 admin 权限为真(这我在初始化适配器时作为参数值传递)。但是我正在努力解决的问题是,在 onCreateViewHolder 方法或 onBindViewHolder 方法中在哪里设置可见性?我现在已经在 onCreateViewHolder 方法中设置了它,因为我只阅读了一些 Whosebug 答案,我们应该避免在 onBindViewHolder 方法中进行大量操作。但我想知道一个明确的答案。

以下是供参考的代码示例:

适配器class声明:

class NoticesAdapter(options: FirestoreRecyclerOptions<NoticeModel>,
                    private val isAdmin: Boolean,
                    private val listener: INoticeListAdapter):
        FirestoreRecyclerAdapter<NoticeModel, NoticesAdapter.NoticeViewHolder>(options)

onCreateViewHolder 方法:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoticeViewHolder {

        val noticeListView = LayoutInflater.from(parent.context).inflate(R.layout.item_notice, parent, false)
        val noticeListViewHolder = NoticeViewHolder(noticeListView)

        if (!isAdmin)
        {
            noticeListViewHolder.deleteNoticeBtn.visibility = GONE
        }

        // On clicking the delete button on a notice by the admin
        noticeListViewHolder.deleteNoticeBtn.setOnClickListener {
            val noticeSnapshot = snapshots.getSnapshot(noticeListViewHolder.adapterPosition)
            listener.deleteNoticeBtnListener(noticeSnapshot)
        }

        return noticeListViewHolder
    }

onBindViewHolder 方法:

override fun onBindViewHolder(holder: NoticeViewHolder, position: Int, model: NoticeModel) {
        holder.noticeText.text = model.noticeText
        holder.noticeAuthor.text = MyUtils.getUserName()
        holder.noticePostDate.text = model.datePosted
        holder.noticePostTime.text = model.timePosted

    }

A RecyclerView.Adapter 它的作用是:回收物品(顾名思义)。该列表不会同时对数据源上的每个项目有一个视图。适配器确保在内存中有足够的视图,以便始终平滑地呈现列表。当一行通过滚动离开视野时,该视图将被回收以在下一个进入屏幕尺寸的视图中重新使用。

这意味着onCreateViewHolder仅在需要创建视图时调用。通常在适配器启动时,以及当用户快速或不规律地滚动时,以及当数据集发生变化和需要时。

每次需要更新行上的数据以便更新视图时调用另一个方法 onBindViewHolder。每次一行进入屏幕的视图字段时都会调用此方法。

所以教科书的答案是:在 onBindViewHodlder 上做,因为如果属性 isAdmin 发生变化,那么该行将需要更新。通过在 onCreateViewHolder 上执行此操作,这只会在创建行时发生一次。

但是,您的 isAdmin 是无法重新分配的构造函数上的 val,因此这意味着当创建行时,按钮将永远隐藏或可见。这无关紧要,因为您的结构是确定是否是来自另一个来源的管理员,该来源与行数据结构的派生来源分开。

如果在某些情况下你想:

  • 使其在未来更加灵活和易于维护
  • 或者您可能知道在某些情况下会有一个包含管理员而不是管理员行的列表

然后解决方案是将 isAdming 属性移动到您的 NoticeModel,这意味着更改您的数据结构。

如果您想验证上面的任何内容,请获取包含大量项目的数据源,然后添加 2 条日志,一条在 onCreateViewHolder 上,一条在 onBindViewHolder 上。你会看到 on create 只是有时被调用,而 on bind 总是被调用。