Reputation: 1739
I am confused at the moment because of getAdapterPosition()
.
The reason I ask this is because getAdapterPosition()
works according to the call location.
It works in Anonymous Obect's OnClick()
. But if it exsits Anonymous Obect's Field
, it doesn't work.
The value at this time is -1
.
What's the problem?
This is Code
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 ( ERROR LOCATION )
dialogAdapter.setOnItemClickListener(new DialogItemAdapter.OnDialogItemClickListener() {
@Override
public void OnItemClick(View itemView, int pos) {
Log.d(TAG, "OnItemClick: ");
String data = dialogAdapter.getItem(pos).getPart(); // ERROR
}
});
Is it a grammatical problem for Java?
please help me.
Thank you
Upvotes: 0
Views: 287
Reputation: 21053
The reason for this is already mentioned in the comment docs of Source code.
- 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}.
That means in case Adapter
is still in inflating state then getAdapterPosition
will return -1
. If you read the comments its use to calculate the position of ViewHolder
to react on User UI action (click, touch etc).
What you have done with an anonymous class you have set a global property with getAdapterPosition()
which will get set at the time of initialization. It can be -1 sometimes depending on the Adapters State .
Also it will get you in trouble if you use notifyItemRemoved()
because it will not update the saved property for other positions. lets say you have 0..10 items items in adapter and you call notifyItemRemoved(0)
after 0 is removed your anonymous property will be still holding 1..10
because they did not get notified which will end up in ArrayIndexOutOfBound
. That's why you should use getAdapterPosition()
to calculate the position at the time of action.
Also just to be on safe side always check for 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);
}
}
});
Upvotes: 1
Reputation: 1692
/**
* ...
* @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.
*/
So this means the // did not work
line got called when the item has been removed from the adapter, or the ViewHolder has been recycled. In other words, your ViewHolder is not currently shown inside your recycler view.
When the // work well
line got called the ViewHolder was actually active inside the recycler view.
I suspect that you set the listener inside the constructor of your ViewHolder, and when the constructor runs, the viewholder is not yet inside the recycler view. If you set your click listener inside your onBindViewHolder
, it should work I think.
Upvotes: 1