代码之家  ›  专栏  ›  技术社区  ›  GuilhE

使用MVVM架构的ViewModel注入(内部视图)

  •  1
  • GuilhE  · 技术社区  · 8 年前

    这就是我如何创建 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;
        }
    }
    

    因为我用的是匕首,所以我不会创造 ViewModels 适配器 Android.View .我想这是有道理的,因为我的 适配器 类型,这些视图可以有Y ViewModel

    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 {...}
    

    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);
            ...
        }
    }
    

    现在,这种方法适用于活动、片段等,但当我使用视图时,我必须创建一个 视图注入 This is how I do it (阅读,直到到达 “ViewInjection几乎是其他喷油器的复制品。”

    我的问题是:这是一个好方法吗?我在正确使用MVVM和Dagger吗?有没有更好的方法来实现这一点而不创建 视图注入

    谢谢你抽出时间。

    适配器 但是如果我想使用视图而不是片段,这种方法是相同的。具有 Adapters 您只能观看。

    2 回复  |  直到 8 年前
        1
  •  2
  •   David Rawson maruti060385    8 年前

    关于是否应该在中插入内部视图,已经有一些讨论 this question

    我个人觉得这有点问题,如果我在一个团队中使用该代码,我更喜欢层之间更大程度的分离。至少

    1. 应该有一个清晰的模型层(例如从存储库或云检索)。这些应该只是数据对象。
    2. 这个 Adapter List RecyclerView .
    3. ViewModel RecyclerView.ViewHolder 应该非常轻,不需要注射。它本质上应该是一个属性包,可以轻松转换为视图的某些属性(例如。, setText() , setColor() )并且可以获取/设置。可以使用 new onBindViewHolder ViewModelFactory )并将其作为适配器的依赖项注入。

    简而言之,模型数据对象应该是“哑的”。这同样适用于 对于个人 ViewHolder 适配器 可以是“智能”的,并且可以接受测试的“智能”依赖项(例如 ViewModelFactory 可以使用匕首2注入你的活动或碎片。

        2
  •  0
  •   Sapan Diwakar    4 年前

    虽然我同意 David's answer 不应该这样做,如果您仍然想这样做,可以通过以下活动:

    override val activity: FragmentActivity by lazy {
        try {
            context as FragmentActivity
        } catch (exception: ClassCastException) {
            throw ClassCastException("Please ensure that the provided Context is a valid FragmentActivity")
        }
    }
    override var viewModel = ViewModelProviders.of(activity).get(SharedViewModel::class.java)
    

    对此进行了更详细的讨论 here