Reputation: 925
so i tried to implement onClickListener
for my RecyclerView for the first time and I've been wondering if what i did is actually worth doing. In my application i have different Recycler Views, and i don't need both onClickListeners
and onLongClickListeners
at the same time in most of them, so I wanted to do it so that i don't have to implement them both in my .setOnItemClickListener
. I basically check which onClickListener
is set up with enum mode, and then according to that i set my listeners in onCreateViewHolder
. Does it even makes sense to do that? Or should i just implement both listeners and don't do what i did in my code?
public class FreindRecyclerViewAdapter extends RecyclerView.Adapter<FreindRecyclerViewAdapter.MyViewHolder> {
private ClickListener clickListener ;
private LongClickListener longClickListener;
private Context context;
private List<String> friends;
private ListenerMode mode;
public enum ListenerMode {NullMode, ShortClick, LongClick}
public interface ClickListener {
void onItemClick(int position, View v);
}
public interface LongClickListener {
void onItemLongClick(int position, View v);
}
public void setOnItemClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
mode = ListenerMode.ShortClick;
}
public void setOnLongItemClickListener(LongClickListener longItemClickListener) {
this.longClickListener = longItemClickListener;
mode = ListenerMode.LongClick;
}
public FreindRecyclerViewAdapter (Context context, List<String> friends) {
this.context = context;
this.friends = friends;
this.mode = ListenerMode.NullMode;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view;
view = LayoutInflater.from(context).inflate(R.layout.friend_item, viewGroup, false);
final MyViewHolder myViewHolder = new MyViewHolder(view);
if(mode == ListenerMode.ShortClick) {
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clickListener.onItemClick(myViewHolder.getAdapterPosition(), view);
}
});
} else if (mode == ListenerMode.LongClick) {
myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
longClickListener.onItemLongClick(myViewHolder.getAdapterPosition(), view);
return true;
}
});
}
return myViewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {
myViewHolder.friendName.setText(friends.get(position));
}
@Override
public int getItemCount() {
return friends.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
private TextView friendName;
public MyViewHolder(View itemView) {
super(itemView);
friendName= itemView.findViewById(R.id.friendName_ID);
}
}
}
EDIT: Now that i think of it, i don't even know why it does work, like when i set up my RecyclerView, adapter and all in my code below, I first tell the adapter about the list I want to show on the screen in it's constructor recyclerViewAdapter = new FreindRecyclerViewAdapter(this, friends);
, so this is when onCreateViewHolder
is called for my views. So now when everything is created (ViewHolders) I call the function to set up the OnClickListener, which in my code adds different listeners according to the mode
that is set up, and those listeners are added in onCreateViewHolder
, which was already called, so why does RecyclerViewAdapter (and how does it know to) call the onCreateViewHolder
again to add the listeners?
friends = new ArrayList<>();
friends.add("Josh");
friends.add("Mike");
friends.add("Ashley");
friends.add("Jess");
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView = findViewById(R.id.recyclerViewFriend_ID);
recyclerViewAdapter = new FreindRecyclerViewAdapter(this, friends);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(recyclerViewAdapter);
DividerItemDecoration itemDecor = new DividerItemDecoration(this, linearLayoutManager.getOrientation());
recyclerView.addItemDecoration(itemDecor);
recyclerViewAdapter.setOnLongItemClickListener(new FreindRecyclerViewAdapter.LongClickListener() {
@Override
public void onItemLongClick(int position, View v) {
Toast.makeText(FriendActivity.this, "Long Click. Position:" + Integer.toString(position), Toast.LENGTH_SHORT).show();
}
});
Upvotes: 1
Views: 431
Reputation: 18677
It's ok but it can be better.
1) You are creating a click listener and long click listener for every position
You don't need to create a listener for every position like you are doing here:
myViewHolder.itemView.setOnClickListener(new View.OnClickListener() ...
and
myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() ...
Since they are performing the very similar action, you can create only one click and longclick listener and share with all views. To make that, move the itemView.setOnClickListener()
and the itemView.setOnLongClickListener()
to the ViewHolder
class.
You need to save the position in the ViewHolder as well. So, they will be able to store their own position.
2) You don't need to create a enum
You don't need to create a enum to check if current mode (click or long click). Instead, you can just check if the variables are null, for example.
In the end, you can have a code like this:
public class FreindRecyclerViewAdapter extends RecyclerView.Adapter<FreindRecyclerViewAdapter.MyViewHolder> {
private ClickListener clickListener ;
private LongClickListener longClickListener;
private Context context;
private List<String> friends;
public interface ClickListener {
void onItemClick(int position, View v);
}
public interface LongClickListener {
void onItemLongClick(int position, View v);
}
public void setOnItemClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
public void setOnLongItemClickListener(LongClickListener longItemClickListener) {
this.longClickListener = longItemClickListener;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view;
view = LayoutInflater.from(context).inflate(R.layout.friend_item, viewGroup, false);
return new MyViewHolder(view, i, clickListener, longClickListener);;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {
myViewHolder.friendName.setText(friends.get(position));
}
@Override
public int getItemCount() {
return friends.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements
View.OnLongClickListener, View.OnClickListener {
private TextView friendName;
private int position;
public MyViewHolder(View itemView, int position) {
super(itemView);
friendName = itemView.findViewById(R.id.friendName_ID);
this.position = position;
if (clickListener != null) {
itemView.setOnClickListener(this);
}
if (longClickListener != null) {
itemView.setOnLongClickListener(this);
}
}
@Override
public void onClick(View view) {
if (clickListener != null) {
clickListener.onItemClick(position, view);
}
}
@Override
public boolean onLongClick(View view) {
if (longClickListener != null) {
longClickListener.onItemLongClick(position, view);
return true;
} else {
return false;
}
}
}
}
View.OnClickListener
and View.LongClickListener
. So, you don't need to instantiate a new listener for every position.FreindRecyclerViewAdapter.setOnItemClickListener(object);
FreindRecyclerViewAdapter.setOnLongItemClickListener(object);
null
as parameter. If you check the code in MyViewHolder
, you can see that any action is performed when those listeners are nullHope I could help and share more ways to achieve what you want!!!
Upvotes: 1