不同列表和对象使用多个适配器还是一个适配器 - 代码性能

3

在性能方面,在Android应用中实现以下哪种选项更好:

  • 为每个对象列表使用多个适配器,每个适配器具有不同的布局
  • 使用单个适配器处理不同的数据

假设我们需要创建:

  • 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;
        }
    
    }
    

    } }

还有另一种方法可以做到这一点。 每个列表只需要单个适配器,例如:

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();
}

就性能而言,实现哪种方法更好?如果我决定为不同的列表实现一个适配器,是否会出现明显的延迟或性能问题?

1个回答

8
无论您的布局和处理附加到单元格的复杂性如何,我建议您为每个列表使用单个适配器。
以下是一个简单的图片,用于说明RecyclerView的主要操作: RecyclerView 操作 根据RecyclerView.Adapter的文档:当需要创建新的可重用单元格时(取决于屏幕上可以显示的单元格数),将调用createViewHolder()方法。因此,在其中执行if语句不会对性能产生太大影响。如果屏幕上显示10个单元格,则可能会多次调用onCreateViewHolder()超过10次。 问题可能出现在onBindViewHolder()上,每当RecyclerView需要显示新单元格时都会调用该方法。因此,如果您有100个元素的列表,并且用户向下滑动到底部,则系统将执行比通常多100个if语句。
此外,如果您为每个列表制作单个适配器,则我认为您的代码将更易于维护。
最后,我并不确定通过为整个应用程序使用一个适配器来减少系统效率。性能损失不会很明显。我的意思是,最重要的是确保您的代码易于理解,否则您将花费时间在以后调试代码。我建议您通过在onCreateViewHolder和onBindViewHolder(如果您感兴趣,则更多)上设置断点来测试RecyclerView的生命周期,以了解它们何时被调用。
希望这可以帮助您!祝您好运并享受应用程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接