Android RecyclerView.ViewHolders 中具有不同布局的 DataBinding
Android DataBinding in RecyclerView.ViewHolders with different layouts
我正在尝试在新项目中使用 android 的数据绑定功能,到目前为止我对此非常满意。
但现在我在我的 recyclerviews viewholder 中遇到了一个问题。
我的 viewholder 使用不同的布局(基于创建时的视图类型)
public MediaViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
switch(viewType){
case HEADER:
int layout = R.layout.item_media_header;
break;
case DEFAULT:
int layout = R.layout.item_media_default;
break;
case SMALL:
int layout = R.layout.item_media_small;
break;
}
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new MediaViewHolder(v);
}
所有这 3 种布局都具有相同的视图,只是排列方式不同。所以模型到视图的绑定是一样的。
无论如何,基于这些布局 android 创建
- ItemMediaHeaderBinding
- ItemMediaDefaultBinding
- ItemMediaSmallBinding
这很糟糕,因为它会迫使我创建 3 个不同的 ViewHolder 类 或通过检查使用的布局来实例化正确的绑定 Class。
这个案例有最佳实践吗?是否有可能简单地为这三个绑定 类 创建一个超类,例如 "ItemMediaBinding"。
提前致谢。
所以,我最后做的是创建一个 BaseViewHolder.class
,创建扩展此 BaseViewHolder
的其他 ViewHolder
classes,这样我的 RecyclerView.Adapter
看起来仍然很干净,因为我最终得到了这样的东西 ViewHolder
:
public class BaseVH extends RecyclerView.ViewHolder {
private ViewDataBinding mBinding;
public BaseVH(ViewDataBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
public void displayPost(final NewsItem post) {
PostItemViewModel vm = new PostItemViewModel();
vm.getPost().set(post);
mBinding.setVariable(BR.viewModel, vm);
}
}
public class TextPostVH extends BaseVH {
private final PostTextBinding mBinding;
public TextPostVH(final PostTextBinding binding) {
super(binding);
mBinding = binding;
}
//Have a method like this in the BaseVH.class
@Override
public void displayPost(final NewsItem post) {
if (mBinding.getViewModel() == null) {
mBinding.setViewModel(new PostItemViewModel());
}
mBinding.getViewModel().getPost().set(post);
}
}
所以你可以简单地调用 onBindViewHolder
:
@Override
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){
holder.displayPost(mPosts.get(position));
((AdVH) holder).displayAd();
} else {
holder.displayPost(mPosts.get(position));
}
}
您可以在 data
标签中的 layouts
中指定 Binding class names
:
<data class="PostTextBinding" />
但我认为您不能在不同的布局中使用相同的 class 名称。您可以在 GitHub.
找到我的(示例)项目
解释了另一种解决方案here on Github。他们创造了一个(真正的)通用的 RecyclerView.Adapter
,但我发现这个……此刻对我来说有点太多了。
我写了一个库:The UniqueAdapter With DataBinding
只需使用方法:
public abstract boolean setVariable(int variableId, Object value);
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof UniqueViewHolder) {
ItemModel item = getItem(position);
UniqueViewHolder vh = ((UniqueViewHolder) holder);
vh.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.viewModel, item);
if (mPresenter != null) {
vh.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.presenter, mPresenter);
}
vh.dataBinding.executePendingBindings();
}
}
@Amylinn 是对的,这真的很适合你,你可以让它变得更加简单:
// Only one ViewHolder at all
public class BaseVH extends RecyclerView.ViewHolder {
private ViewDataBinding mBinding;
public BaseVH(ViewDataBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
public ViewDataBinding() {
return mBinding;
}
}
在onBindViewHolder
中:
@Override
public void onBindViewHolder(final BaseVH holder, final int position) {
// Just use "model" as name in any layouts
holder.getBunding().setVariable(BR.model, mPosts.get(position));
}
但是您仍然需要在 onCreateViewHolder
中创建具有不同布局的视图持有者
或者如果你喜欢使用委托,你可以看看这个方法 - https://github.com/drstranges/DataBinding_For_RecyclerView
我正在尝试在新项目中使用 android 的数据绑定功能,到目前为止我对此非常满意。
但现在我在我的 recyclerviews viewholder 中遇到了一个问题。
我的 viewholder 使用不同的布局(基于创建时的视图类型)
public MediaViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
switch(viewType){
case HEADER:
int layout = R.layout.item_media_header;
break;
case DEFAULT:
int layout = R.layout.item_media_default;
break;
case SMALL:
int layout = R.layout.item_media_small;
break;
}
View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new MediaViewHolder(v);
}
所有这 3 种布局都具有相同的视图,只是排列方式不同。所以模型到视图的绑定是一样的。
无论如何,基于这些布局 android 创建
- ItemMediaHeaderBinding
- ItemMediaDefaultBinding
- ItemMediaSmallBinding
这很糟糕,因为它会迫使我创建 3 个不同的 ViewHolder 类 或通过检查使用的布局来实例化正确的绑定 Class。
这个案例有最佳实践吗?是否有可能简单地为这三个绑定 类 创建一个超类,例如 "ItemMediaBinding"。
提前致谢。
所以,我最后做的是创建一个 BaseViewHolder.class
,创建扩展此 BaseViewHolder
的其他 ViewHolder
classes,这样我的 RecyclerView.Adapter
看起来仍然很干净,因为我最终得到了这样的东西 ViewHolder
:
public class BaseVH extends RecyclerView.ViewHolder {
private ViewDataBinding mBinding;
public BaseVH(ViewDataBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
public void displayPost(final NewsItem post) {
PostItemViewModel vm = new PostItemViewModel();
vm.getPost().set(post);
mBinding.setVariable(BR.viewModel, vm);
}
}
public class TextPostVH extends BaseVH {
private final PostTextBinding mBinding;
public TextPostVH(final PostTextBinding binding) {
super(binding);
mBinding = binding;
}
//Have a method like this in the BaseVH.class
@Override
public void displayPost(final NewsItem post) {
if (mBinding.getViewModel() == null) {
mBinding.setViewModel(new PostItemViewModel());
}
mBinding.getViewModel().getPost().set(post);
}
}
所以你可以简单地调用 onBindViewHolder
:
@Override
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){
holder.displayPost(mPosts.get(position));
((AdVH) holder).displayAd();
} else {
holder.displayPost(mPosts.get(position));
}
}
您可以在 data
标签中的 layouts
中指定 Binding class names
:
<data class="PostTextBinding" />
但我认为您不能在不同的布局中使用相同的 class 名称。您可以在 GitHub.
找到我的(示例)项目解释了另一种解决方案here on Github。他们创造了一个(真正的)通用的 RecyclerView.Adapter
,但我发现这个……此刻对我来说有点太多了。
我写了一个库:The UniqueAdapter With DataBinding
只需使用方法:
public abstract boolean setVariable(int variableId, Object value);
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(holder instanceof UniqueViewHolder) {
ItemModel item = getItem(position);
UniqueViewHolder vh = ((UniqueViewHolder) holder);
vh.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.viewModel, item);
if (mPresenter != null) {
vh.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.presenter, mPresenter);
}
vh.dataBinding.executePendingBindings();
}
}
@Amylinn 是对的,这真的很适合你,你可以让它变得更加简单:
// Only one ViewHolder at all
public class BaseVH extends RecyclerView.ViewHolder {
private ViewDataBinding mBinding;
public BaseVH(ViewDataBinding mBinding) {
super(mBinding.getRoot());
this.mBinding = mBinding;
}
public ViewDataBinding() {
return mBinding;
}
}
在onBindViewHolder
中:
@Override
public void onBindViewHolder(final BaseVH holder, final int position) {
// Just use "model" as name in any layouts
holder.getBunding().setVariable(BR.model, mPosts.get(position));
}
但是您仍然需要在 onCreateViewHolder
或者如果你喜欢使用委托,你可以看看这个方法 - https://github.com/drstranges/DataBinding_For_RecyclerView