3
votes

In terms of performance what is better option to implement in an android app:

  • multiple adapters for every single list of objects with different layouts,
  • single adapter which handles with different data.

Let's suppose we need to create

  • Comments,
  • Videos,

  • Questions

    lists in adapter to display data properly. Each list belongs to different layout, so that we have different TextViews, ImageViews and so on.

    public class FilesAdapter extends RecyclerView.Adapter {

    public static final int VIDEO_FILES_ADAPTER = 1; public static final int COMMENT_ADAPTER = 2; public static final int QUESTIONS_ADAPTER = 3;

    private int CURRENT_ADAPTER;

    private List videoFiles; private List comments; private List questions;

    boolean isForUser;

    public FilesAdapter(int currentAdapter, List videoFiles, boolean isForUser){ this.videoFiles = videoFiles; this.CURRENT_ADAPTER = currentAdapter; this.isForUser = isForUser; }

    public FilesAdapter(int currentAdapter, List comments){ this.comments = comments; this.CURRENT_ADAPTER = currentAdapter; }

    public FilesAdapter(int currentAdapter, List questions, int unusedVariable){ this.questions = questions; this.CURRENT_ADAPTER = currentAdapter; }

    @NonNull @Override public FilesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; FilesViewHolder viewHolder;

    switch(CURRENT_ADAPTER){
    
        case VIDEO_FILES_ADAPTER:
    
            if(isForUser){
                view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_layout_file_user, parent, false);
            }else{
                view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_layout_file_main, parent, false);
            }
    
            viewHolder = new FilesViewHolder(VIDEO_FILES_ADAPTER, view, isForUser);
    
            return viewHolder;
    
        case COMMENT_ADAPTER:
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_layout_comment, parent, false);
            viewHolder = new FilesViewHolder(COMMENT_ADAPTER, view, false);
    
            return viewHolder;
    
        case QUESTIONS_ADAPTER:
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_layout_question, parent, false);
            viewHolder = new FilesViewHolder(QUESTIONS_ADAPTER, view, false);
    
            return viewHolder;
    }
    
    return null;
    

    }

    @Override public void onBindViewHolder(@NonNull FilesViewHolder holder, int position) {

    switch (CURRENT_ADAPTER){
    
        case VIDEO_FILES_ADAPTER:
            holder.videoTitle.setText(videoFiles.get(position).getFileName());
            holder.videoDescription.setText(videoFiles.get(position).getFileDescription());
            if(isForUser){
                holder.videoDate.setText(videoFiles.get(position).getFileCreatedAt());
            }else{
                holder.videoUser.setText(videoFiles.get(position).getUsername());
            }
    
            holder.videoCount.setText(videoFiles.get(position).getWatched());
            break;
    
        case COMMENT_ADAPTER:
            holder.commentComment.setText(comments.get(position).getComment());
            holder.commentUsername.setText(comments.get(position).getUsername());
            holder.commentCreatedAt.setText(comments.get(position).getCreatedAt());
            break;
    
        case QUESTIONS_ADAPTER:
            holder.questionTitle.setText(questions.get(position).getProviderUsername());
            break;
    }
    

    }

    @Override public int getItemCount() {

    switch (CURRENT_ADAPTER){
        case VIDEO_FILES_ADAPTER:
            return videoFiles.size();
        case COMMENT_ADAPTER:
            return comments.size();
        case QUESTIONS_ADAPTER:
            return questions.size();
    }
    
    return 0;
    

    }

    public static class FilesViewHolder extends RecyclerView.ViewHolder{

    private static final int VIDEO_FILES_ADAPTER = 1;
    private static final int COMMENT_ADAPTER = 2;
    private static final int QUESTIONS_ADAPTER = 3;
    
    private int CURRENT_ADAPTER;
    
    // Related to audio file class
    public TextView videoTitle, videoDescription, videoDate, videoUser, videoCount;
    
    // Related to comment class
    private TextView commentComment, commentUsername, commentCreatedAt;
    
    // Related to subscription class
    private TextView questionTitle;
    
    
    // @param isForUser applies only if CURRENT_ADAPTER == VIDEO_FILES_ADAPTER
    public FilesViewHolder(int CURRENT_ADAPTER, View itemView, boolean isForUser) {
        super(itemView);
    
        switch(CURRENT_ADAPTER){
    
            case VIDEO_FILES_ADAPTER:
    
                videoTitle = itemView.findViewById(R.id.tV_title);
                videoDescription = itemView.findViewById(R.id.tV_description);
                if(isForUser){
                    videoDate = itemView.findViewById(R.id.tV_date);
                }else{
                    videoUser = itemView.findViewById(R.id.tV_username);
                }
                videoCount = itemView.findViewById(R.id.tV_watched);
    
                break;
    
            case COMMENT_ADAPTER:
    
                commentComment = itemView.findViewById(R.id.tV_comment);
                commentUsername = itemView.findViewById(R.id.tV_comment_username);
                commentCreatedAt = itemView.findViewById(R.id.tV_comment_created_at);
    
                break;
    
            case QUESTIONS_ADAPTER:
    
                questionTitle = itemView.findViewById(R.id.tV_question);
    
                break;
        }
    
    }
    

    } }

There is another way to do that. Single adapter for each list e.g.:

public class CommentAdapter extends RecyclerView.Adapter<CommentAdapter.CommentViewHolder>{

private List<Comment> commentList;

public CommentAdapter(List<Comment> comments){
    this.commentList = comments;
}

public static class CommentViewHolder extends RecyclerView.ViewHolder{

    private TextView comment, username, createdAt;

    public CommentViewHolder(View itemView) {
        super(itemView);

        comment = itemView.findViewById(R.id.tV_comment);
        username = itemView.findViewById(R.id.tV_comment_username);
        createdAt = itemView.findViewById(R.id.tV_comment_created_at);
    }
}

@NonNull
@Override
public CommentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_layout_comment, parent, false);

    return new CommentViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull CommentViewHolder holder, int position) {
    holder.comment.setText(commentList.get(position).getComment());
    holder.username.setText(commentList.get(position).getUsername());
    holder.createdAt.setText(commentList.get(position).getCreatedAt());
}

@Override
public int getItemCount() {
    return commentList.size();
}

}

My question is in terms of performance what would be better to implement? Are there going to be any noticeable delays or patches in performance if I decide to implement one adapter for different lists?

1

1 Answers

7
votes

Regardless of the complexity of your layouts and processing attach to your cells, I will recommend you to use single adapter for each list.

Just a small picture to illustrate the mainly operation of the RecyclerView : RecyclerView operation

According to the documentation of the RecyclerView.Adapter : the method createViewHolder() is called when a new reusable cell must be created (depending of the number of cells that could be displayed on the screen). So performing if statements into will not impact the performances that much. onCreateViewHolder() could be call a bit more 10 times if 10 cells are displayed on the screen. The problem may be on the onBindViewHolder() that is called every time the RecyclerView needs to display a new cell. So if you have a list of 100 elements and your user fling to the bottom, the system will perform 100 if statements more than usually.

Moreover, I think that your code will be more maintainable if you make single adapters for each list.

I will conclude by the fact that I'm not really sure the system will be less efficient by the way of one adapter for the whole application. The performance loses will not be noticeable. My meaning is that the most important point is to make sure your code is easy to understand otherwise you will lose time at debugging your code in the future. I advise you to test the RecyclerView lifecycle by putting breakpoints on the onCreateViewHolder and onBindViewHolder (and more if you are curious) to understand when are they called.

I hope it helps you ! Good luck and have fun with your app