1

I already checked this question Android DataBinding in RecyclerView.ViewHolders with different layouts

But in my case, the ViewHolders have a super class BaseViewHolder. All of the ViewHolders have the same outer layout, like a header and a close button but the content layout differ from viewtype to viewtype.

I want to use DataBinding and MVP to handle this views. I am able to get a Binder for every ViewHolder but every binding has a different class-type. All of them are extending ViewDataBinding.

Some code:

public ViewHolderA(ListItemABinding binding) extends BaseViewHolder{
    super(binding);
    ... do stuff with the binding
}

public ViewHolderB(ListItemBBinding binding) extends BaseViewHolder {
    super(binding);
    ... do stuff with the binding
}

public BaseViewHolder(ViewDataBinding binding) extends RecyclerView.ViewHolder {
    super(binding.getRoot());
    //access the header and the button here!!!
}

inside of the Adapter:

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int itemType) {
    switch (itemType) {
        case SmartHomeBase.VIEW_TYPE_A:
            ListItemABinding bindingA = DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.list_item_a, viewGroup, false);
            return new ViewHolderA(bindingA);
        default:
            ListItemBBinding bindingB = DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.list_item_b, viewGroup, false);
            return new ViewHolderB(bindingB);
    }
}

What I get from the DataBindingUtil is ListItemABinding and ListItemBBinding, both containing the Button and the Header I need in the BaseViewHolder. The BaseViewHolder just accept the ViewDataBinding where I can not reach (the easy way) the views I need.

Option 1: I can use findViewById (again) - but that seems not really nice.

Option 2: check instanceof for the DataBindings in BaseViewHolder and cast - seems also not really nice.

Is there an Option 3 I don't see?

Community
  • 1
  • 1
Informatic0re
  • 6,300
  • 5
  • 41
  • 56
  • you dont need access to `View`s from your `ViewHolder`s: all the view related stuff is done in generated `ViewDataBinding` classes – pskink Nov 16 '16 at 11:44
  • What if I want to load an Image like ImageLoader.loadImageAsync()? Therefor I need the view? – Informatic0re Nov 16 '16 at 14:40
  • https://blog.stylingandroid.com/data-binding-part-3/ – pskink Nov 16 '16 at 14:52
  • Do you really need to access your `Views` from your Binding? As an alternative, you could create some `` tags in your layout and pass `Strings`, `Boolean` and everything else, then parse the data in your `View` - and you can use my old answer. I think another option would be to create a "dummy" layout for your `BaseViewHolder` which only contains the header and the button for the purpose of having these available in your Binding. – yennsarah Nov 17 '16 at 06:47
  • some times I really need access! For example I am using a library for a special button or something where I can set a listener for on click just programmatically and not via onClick in xml. Therefor I need access. – Informatic0re Nov 18 '16 at 09:36

1 Answers1

1

There are at least two more possible ways to do this.

One would be to create a separate layout file layout_outer for the outer layout and inflate the inner layout into an inner_container

LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
LayoutOuterBinding binding = DataBindingUtil.inflate(inflater, R.layout.layout_outer, viewGroup, false);
ListItemABinding bindingA = DataBindingUtil.inflate(inflater, R.layout.list_item_a, binding.innerContainer, true);

Then you'd create a constructor

BaseViewHolder(LayoutOuterBinding outer, ViewDataBinding binding)

instead and have all you need in outer.

The opposite way would be possible as well. Just include the parts of your outer layout with <include android:id="@+id/outer" ... /> and access and provide it from the binding bindingA.outer.

tynn
  • 38,113
  • 8
  • 108
  • 143