hightower hightower - 11 months ago 46
Android Question

Android DataBinding in RecyclerView.ViewHolders with different layouts

I'm trying to use androids databinding feature in new project and so far very happy with it.

But now i came across a problem in my recyclerviews viewholder.

My viewholder uses different layouts (based on the viewtype when it gets created)

public MediaViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
case HEADER:
int layout = R.layout.item_media_header;
int layout = R.layout.item_media_default;
case SMALL:
int layout = R.layout.item_media_small;
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new MediaViewHolder(v);

So all of those 3 layouts have the same views in it, only arranged differently. So the binding of the model to the views is the same.

Anyways, based on those layouts android creates

  • ItemMediaHeaderBinding

  • ItemMediaDefaultBinding

  • ItemMediaSmallBinding

Which sucks since it would force me to create 3 different ViewHolder classes or instantiate the right binding Class by checking which layout is used.

Is there a best practice for this case? Is there a possibility to simply create a superclass for those three binding classes like "ItemMediaBinding".

Thanks in advance.

Answer Source

So, what I ended up doing, was to create a BaseViewHolder.class, create other ViewHolder classes that extend this BaseViewHolder, so that my RecyclerView.Adapter still looks clean, because I ended up with something like this as a ViewHolder:

public class BaseVH extends RecyclerView.ViewHolder {
    private ViewDataBinding mBinding;

    public BaseVH(ViewDataBinding mBinding) {
        this.mBinding = mBinding;

    public void displayPost(final NewsItem post) {
        PostItemViewModel vm = new PostItemViewModel();
        mBinding.setVariable(BR.viewModel, vm);

public class TextPostVH extends BaseVH {
    private final PostTextBinding mBinding;

    public TextPostVH(final PostTextBinding binding) {
        mBinding = binding;

    //Have a method like this in the BaseVH.class
    public void displayPost(final NewsItem post) {
        if (mBinding.getViewModel() == null) {
            mBinding.setViewModel(new PostItemViewModel());

So you can simply call in the onBindViewHolder:

public void onBindViewHolder(final BaseVH holder, final int position) {
    //only a ViewHolder containing ads has to be filtered, the others work with displayPost()
    if (holder instanceof AdVH){
        ((AdVH) holder).displayAd();
    } else {

You can specify the Binding class names in your layouts in the data-tag:

 <data class="PostTextBinding" />

But I don't think that you are allowed to use the same class names in different layouts. You can find my (sample) project at GitHub.

Another solution is explained here on Github. They have created a (really) universal RecyclerView.Adapter, but I found this... a little too much for me at this moment.