Is there a way to use the ViewStub inside the RecyclerView?
I am new to android, I was working on a project and on my news page, I am trying to enable a modular RecyclerView feed that shows a question with different response forms, varrying according to the Question type. The way I've done it so far is to use the included and rotate forms when needed. recently, as I added more modules, the application started to slow down significantly, so I am trying to implement ViewStubs.
This is my RecyclerView adapter:
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();
}
}
And this is the ViewHolder class for the adapter:
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;
}
}
}
Now the problem is that the ViewStub that contains a certain layout cannot be re-created with a new one, the reason is that it is removed from the hirarchy view as soon as it leaves the screen, and the symptoms: When scrolling through the RecyclerView list the first list items that fill the screen work perfectly, but others that load when the previous exit from the screen results in the FeedItem being bound to the application with a NullPointerException . (He can't find it in the list layout).
I am looking for a solution the same as ViewStubs, or a way to make them work as expected, since I got a lot of modules and inflated them all in each element as invisible will make my application slow.
source to share
In your method, bindQuestion()
you are referencing two different layouts for bloat, so essentially you have two different view types.
Adapter views have an efficient way to manage this built-in right.
Start by overriding getItemViewType()
. When the element position
receives a layout module_yes_no
, return 0. When it receives a layout module_custom
, return 1.
Then in onCreateViewHolder()
when the parameter viewType
is 0, inflate the view list_item_re_question
complete with layout module_yes_no
. When viewType
== 1, inflate the view version module_custom
.
Now that you get a view in onBindViewHolder()
, it will already have the correct subview, so you start filling out that view as needed. Using getItemViewType()
, RecyclerView
works with you to rework the exact look you want.
You can even have two subclasses FeedItem
, one for module_yes_no
and one for module_custom
, so in onBindViewHolder()
you just check out the class ViewHolder
and branch respectively.
This should help improve the performance of your application.
source to share