This is how I create an Adapter
with MVVM (+Databinding) and Dagger-2.11-rc2:
Adapter:
public class ItemAdapter extends RecyclerView.Adapter<BindableViewHolder<ViewDataBinding>>{
private static int TYPE_A = 0;
private static int TYPE_B = 1;
...
@Override
public BindableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_A) {
return new ItemViewHolder(new ItemRowView(parent.getContext()).getBinding());
}
...
}
@Override
public void onBindViewHolder(BindableViewHolder holder, int position) {
if (holder.getItemViewType() == TYPE_A) {
((ItemViewHolderBinding) holder.getBinding()).getViewModel().setItemModel(((ItemModel) getItem(position)));
}
...
}
private static class ItemViewHolder extends BindableViewHolder<ItemViewHolderBinding> {
ItemViewHolder(ItemViewHolderBinding binding) {
super(binding);
}
}
}
BindableViewHolder:
public abstract class BindableViewHolder<ViewBinding extends ViewDataBinding> extends RecyclerView.ViewHolder {
private ViewBinding mBinding;
public BindableViewHolder(ViewBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
public ViewBinding getBinding(){
return mBinding;
}
}
Since I'm using Dagger I wont be creating the ViewModels
inside the Adapter
instead they will be created (injected) inside their respective Android.View
. And I guess it makes sense because my Adapter
may have X Android.View
types, those views can have Y ViewModel
, etc...
BaseView:
public abstract class BaseView<ViewBinding extends ViewDataBinding, ViewModel extends BaseViewModel> extends FrameLayout {
@Inject
ViewModel mViewModel;
protected ViewBinding mBinding;
protected abstract void initBinding(final ViewBinding binding, final ViewModel viewModel);
...
private void initView(Context context) {
ViewInjection.inject(this);
mBinding = DataBindingUtil...
initBinding(mBinding, mViewModel);
...
}
...
}
BaseViewModel:
public class BaseViewModel extends BaseObservable {...}
ItemRowView (or any View):
public class ItemRowView extends BaseView<ItemRowViewBinding, ItemRowViewModel> {
@Inject
ViewModelA mViewModelA;
@Inject
ViewModelB mViewModelB;
...
@Override
protected void initBinding(ItemRowViewBinding binding, ItemRowViewModel viewModel) {
binding.setViewModel(viewModel);
binding.setViewModelA(mViewModelA);
binding.setViewModelB(mViewModelB);
...
}
}
Now, this approach works fine with Activities, Fragments, etc, but when I use Views I have to create a ViewInjecton because Dagger doesn't have it out of the box. This is how I do it (read until you've reached "ViewInjection is pretty much a copy from other Injectors.")
My question(s) is(are): Is this a good approach? I'm I using MVVM and Dagger correctly? Is there any better way to achieve this without creating ViewInjecton (and using Dagger-2.11)?
Thanks for your time.
ps: I've used the Adapter
example but this approach is the same if I want to use Views instead of Fragments. With Adapters
you are restricted to Views.