(android) getAdapterPosition() 是否仅在 OnClick() 内部起作用?

(android) Does getAdapterPosition() only work inside OnClick()?

我现在很困惑,因为 getAdapterPosition()

我问这个的原因是因为 getAdapterPosition() 根据调用位置工作。

它适用于 Anonymous Obect's OnClick()。但是如果它存在Anonymous Obect's Field,它就不起作用。

此时的值为-1

有什么问题?

这是代码

Adapter.java ( RecyclerView Adpater )

part.setOnClickListener(new View.OnClickListener() {
                int position = getAdapterPosition(); // didn't work
                @Override
                public void onClick(View v) {
                    int position = getAdapterPosition(); // work well
                    if(select == false) {
                        part.setBackgroundColor(context.getResources().getColor(R.color.teal_700));;
                        select = true;
                    }
                    else {
                        part.setBackgroundColor(context.getResources().getColor(R.color.white));;
                        select = false;
                    }
                    listener.OnItemClick(v, position); // or OnItemClick(v, getAdapterPosition()) works well, too
                }
            });

DialogFragment.java(错误位置)

dialogAdapter.setOnItemClickListener(new DialogItemAdapter.OnDialogItemClickListener() {
            @Override
            public void OnItemClick(View itemView, int pos) {
                Log.d(TAG, "OnItemClick: ");
                String data = dialogAdapter.getItem(pos).getPart(); // ERROR

            }
        });

Java是语法问题吗?

请帮助我。

谢谢

来自文档:

/**
* ...
* @return The adapter position of the item if it still exists in the adapter.
* {@link RecyclerView#NO_POSITION} if item has been removed from the adapter,
* {@link RecyclerView.Adapter#notifyDataSetChanged()} has been called after the last
* layout pass or the ViewHolder has already been recycled.
*/

所以这意味着 // did not work 行在项目已从适配器中删除或 ViewHolder 已被回收时被调用。换句话说,您的 ViewHolder 当前未显示在您的回收站视图中。

当调用 // work well 行时,ViewHolder 实际上在回收器视图中处于活动状态。

我怀疑您在 ViewHolder 的构造函数中设置了侦听器,并且当构造函数运行时,viewholder 尚未在回收器视图中。如果您在 onBindViewHolder 中设置点击侦听器,我认为它应该可以工作。

原因在源代码的注释文档中已经提到。

  • Note that if you've called {@link RecyclerView.Adapter#notifyDataSetChanged()}, until the * next layout pass, the return value of this method will be {@link #NO_POSITION}.

这意味着如果 Adapter 仍处于充气状态,那么 getAdapterPosition 将 return -1 。如果您阅读评论,它用于计算 ViewHolder 的位置以对用户 UI 操作(点击、触摸等)做出反应。

您对匿名 class 所做的是您设置了全局 属性 和 getAdapterPosition(),它将在初始化时设置。它有时可以是 -1,具体取决于适配器状态。

如果您使用 notifyItemRemoved() 也会给您带来麻烦,因为它不会为其他位置更新已保存的 属性。假设你在适配器中有 0..10 个项目,你在删除 0 后调用 notifyItemRemoved(0) 你的匿名 属性 将仍然持有 1..10 因为他们没有得到通知这将结束在 ArrayIndexOutOfBound 中。这就是为什么您应该使用 getAdapterPosition() 来计算操作时的位置。

另外,为了安全起见,请始终检查 NO_POSTION

part.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            if (position != RecyclerView.NO_POSITION) {
                if (select == false) {
                    part.setBackgroundColor(context.getResources().getColor(R.color.teal_700));
                    select = true;
                } else {
                    part.setBackgroundColor(context.getResources().getColor(R.color.white));
                    select = false;
                }
                listener.OnItemClick(v, position);
            }
        }
    });