有没有办法在RecyclerView中使用ViewStub?

Or *_*ner 4 data-binding android viewstub android-viewholder android-recyclerview

我是android的新手,我一直在从事一个项目,并且在我的新闻提要页面中,我尝试包括一个模块化提要RecyclerView,该提要显示具有不同答案形式的问题,并根据Question类型进行变化。到目前为止,我这样做的方法是使用include并在需要时将表单显示为可见。最近,由于我添加了更多模块,因此该应用开始明显减速,因此我尝试实现ViewStubs。

这是我的RecyclerView适配器:

public class ReQuestionAdapter extends RecyclerView.Adapter<FeedItem> {
private ArrayList<Question> myQuestions;
public ReQuestionAdapter(Context context, ArrayList<Question> questions) {
    myQuestions = questions ;
}

@Override
public FeedItem onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_item_re_question, parent, false);
    return new FeedItem(view);
}

@Override
public void onBindViewHolder(FeedItem holder, int position) {
    Question q = myQuestions.get(position);
    holder.bindQuestion(q);
}

@Override
public int getItemViewType(int position) {
    return 0;
}

@Override
public int getItemCount() {
    return myQuestions.size();
}
}
Run Code Online (Sandbox Code Playgroud)

这是适配器的ViewHolder类:

public class FeedItem extends RecyclerView.ViewHolder{
private Question mQuestion;
public TextView tvName;
public TextView tvTime;
public TextView tvContent;
public ProfilePictureView profilePictureView;
public ViewStub moduleView;
private int moduleType;

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

}

public void bindQuestion(Question question) {
    mQuestion = question;
    tvTime = (TextView) itemView.findViewById(R.id.li_q_date);
    tvContent = (TextView) itemView.findViewById(R.id.li_q_content);
    moduleView = (ViewStub) itemView.findViewById(R.id.module_viewstub);
    tvTime.setText(TimeHandler.When(mQuestion.publish_time));
    tvContent.setText(mQuestion.content);
    moduleType = question.type;
        switch (moduleType) {
            case Question.TYPE_YN:
                moduleView.setLayoutResource(R.layout.module_yes_no);
                moduleView.inflate();
                break;
            case Question.TYPE_CUSTOM:
                moduleView.setLayoutResource(R.layout.module_custom);
                moduleView.inflate();
                break;
            default:
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,包含特定布局的ViewStub无法用新布局重新充气,其原因是,一旦离开屏幕,它就会从视图层次结构中删除,出现的症状是: RecyclerView是填充屏幕的第一个列表项,它们工作正常,但是其他项在前一个离开屏幕时加载,则导致FeedItem绑定带来NullPointerException。(它在列表项布局中找不到)。

我正在寻找一种与ViewStubs一样有效的解决方案,或者一种使它们正常工作的方法,因为我有很多模块,并且将每一项中的所有内容都夸大为不可见会使我的应用变慢。

kri*_*son 5

在您的bindQuestion()方法中,您要引用两种不同的布局以进行充气,因此实质上您具有两种不同的视图类型。

适配器视图具有一种有效的方法来处理此内置事件。

从覆盖开始getItemViewType()。当位于的项目position获得module_yes_no布局时,返回0。当获得module_custom布局时,返回1。

然后在中onCreateViewHolder(),当viewType参数为0时,为list_item_re_question包含module_yes_no布局的视图填充视图。当viewType== 1时,增加module_custom视图的版本。

现在,当您在中获得视图时onBindViewHolder(),它将已经具有正确的子视图,因此您可以根据需要继续填写该视图。通过使用getItemViewType()RecyclerView您可以与一起回收所需的确切视图。

您甚至可以拥有两个FeedItem子类,一个用于module_yes_no,一个用于module_custom,因此在中onBindViewHolder(),您只需检查ViewHolder和分支的类即可。

这应该有助于提高应用程序的性能。