1

I have 5 row to display in RecyclerView. When user clicks to one of the items, another activity opens. Each item has starts different activity. I handled the click event like below.

switch (getAdapterPosition()) {
                case 1:
                    ActivityUtil.startActivity(itemView.getContext(), BlablaActivity.class);
                    break;
                //other cases
}

It works correctly. But what if a new item is added to the list in the future? For every single item, I have to add a new case to the switch-case. This is not a proper solution according to Open Closed Principle. How should I handle it? Any suggestions would be great...

cagin
  • 89
  • 7
  • 1
    you can not avoid this. since you have to open different activity (or we can say perform different action) on each item. On e thing you can do is to name activity in resemble to their related item position in list like activity_1 for the activity to open at first item. – nikhil bansal Oct 18 '18 at 14:11
  • 1
    What you can do is Store the activity the items refer in the list, and do it dynamic – Joaquín Oct 18 '18 at 14:22
  • 1
    Why don't you just create a POJO where it also stores the activity class that you would like to trigger as a field? – tingyik90 Oct 18 '18 at 14:37
  • @JoaquinAlvarez Thank you. Your approach was helpful. I just create activityName variable as Class instead of String. – cagin Oct 19 '18 at 06:39

3 Answers3

2

First Save the Activity the items refers in your db and then add it to your typed list model if is the case like

yourlist.java
....
private String BLABLA;
private String BLABLA1;
private String ActivityName;
....

Then in your Adapter OnBindViewholder OnClick do Someting Like This

  @Override
        public void onClick(View v) {

            activityString = singleItem.getActivityName();
            Intent intent= new Intent(context, Class.forName(activityString));
            context.startActivity(intent);
        }
    });
Joaquín
  • 1,116
  • 1
  • 10
  • 26
1

Ideally, you would add a Class<? extends Activity> field to the class that represents your RecyclerView items. Then you could simply access this field in your click listener (this code would be inside onCreateViewHolder()):

holder.itemView.setOnClickListener(v -> {
    int position = holder.getAdapterPosition();

    if (position != RecyclerView.NO_POSITION) {
        Class<? extends Activity> activityClass = items.get(position).getActivityClass();
        ActivityUtil.startActivity(v.getContext(), activityClass);
    }
});

This way, each item is responsible for knowing where to go when it is clicked. You can add new items to your list without ever having to touch the adapter code.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
0

It can be handled easily if you're strictly making the RecyclerView adapter working as a view only, i.e only showing the data with the view. All the logic decision responsibility should be delegate back to the parent activity or fragment. This can be achieved by using a Callback/Listener.

Whenever there is a click event in the RecyclerView item, tell the parent activity or fragment to handle it.

You need to change your adapter to something like this:

public class YourAdapter extends RecyclerView.Adapter<YourAdapter.ViewHolder> {

    // Local variable for listener
    private OnItemClickListener listener;

    // Listener interface
    public interface OnItemClickListener {
        void onItemClick(View itemView, int position);
    }

    // set the listener on parent activity or fragment
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }


    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

      ....

      public ViewHolder(final View itemView) {
        super(itemView);

        itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) return;
                    // tell the parent to handle the item.
                    listener.onItemClick(itemView, position);
                }
            });
      }

    }
}

Then you can use the following to handle the click:

// assuming adapter is your adapter
adapter.setOnItemClickListener(new ContactsAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        handleItemClickByPosition(position);
    }
});

...

private void handleItemClickByPosition(int position) {
   switch (getAdapterPosition()) {
     case 1:
       ActivityUtil.startActivity(itemView.getContext(), BlablaActivity.class);
       break;
       //other cases
  }
}

Hence you don't need to change the Adapter whenever there is new item in your Adapter.

ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96