我想将两个类混合并匹配到recyclerView,ItemA和ItemB中。为了做到这一点,我给它们一个BaseItem基类,这样它们就可以作为一个List传递。然后在我的RecyclerAdapter的getItemViewType方法中,我计算出类是什么,这样我就可以使用正确的Viewholder。
此时我内心的反模式本能开始迸发。我一般认为,如果你必须弄清楚具体类是什么来处理一个对象,那么它不应该有一个基类。这是错误的做法吗?我一直都找不到人们做同样事情的例子。
有没有一个很好的替代方案? 我把一些代码放在一起来说明我的观点。
public class ItemRecyclerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private FragmentManager fragmentManager;
private static final int TYPE_A = 0;
private static final int TYPE_B = 1;
private final LayoutInflater inflater;
private List<BaseItem> items;
public ItemRecyclerAdapter(Context context, List<BaseItem> items, FragmentManager fragmentManager) {
this.fragmentManager = fragmentManager;
inflater = LayoutInflater.from(context);
this.items = items;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_A:
ViewGroup v = // Get viewGroup
ViewHolderA viewHolderA = new ViewHolderA(v);
return viewHolderA;
default:
ViewGroup defaultViewGroup = // Get viewGroup
ViewHolderB viewHolderB = new ViewHolderB(defaultViewGroup);
return viewHolderB;
}
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
BaseMenuItem item = items.get(position);
switch (holder.getItemViewType()) {
case TYPE_A:
ViewHolderA va = (ViewHolderA) holder;
ViewHolderA.setData((ItemA) item);
break;
case TYPE_B:
ViewHolderB vb = (ViewHolderB) holder;
ViewHolderB.setData((ItemB) item);
break;
}
}
@Override
public int getItemViewType(int position) {
BaseMenuItem item = items.get(position);
boolean IsItemTypeA = item.getClass() == ItemA.class;
if (IsItemTypeA) {
return TYPE_A;
}
return TYPE_B;
}
@Override
public int getItemCount() {
if (items == null) {
return 0;
}
return items.size();
}
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
public BaseViewHolder(View itemView) {
super(itemView);
}
}
private class ViewHolderA extends BaseViewHolder {
// ViewHolder stuff here.
}
private class ViewHolderB extends BaseViewHolder {
// ViewHolder stuff here.
}
}
答案 0 :(得分:1)
我个人认为这不是反模式。对于那些场景,我已经实现了一个名为委托适配器的模式,这是对this文章(推荐讲座)的概念的修改。
我建议您对当前的实施进行一些修改:
BaseItem
中指定一个声明其视图类型的抽象方法,并让它们实现所述方法。像getViewType
之类的东西可以避免令人讨厌的getClass
比较。答案 1 :(得分:1)
个人认为,如果这两个模型没有逻辑关系,那么它将被视为反模式,因此不共享任何共同属性,或者不能用抽象来表达。
如果您的唯一目标是仅传递包含两个模型的列表,请传递protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConstraintSet set = new ConstraintSet();
ImageView imageView1 = new ImageView(this);
imageView1.setImageResource(R.mipmap.ic_launcher_round);
TextView textView = (TextView)findViewById(R.id.text1);
int imgId = 100+1;
imageView1.setId(imgId);
imageView1.setAdjustViewBounds(true);
ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.testLayout);
layout.addView(imageView1);
set.clone(layout);
set.connect(imgId, ConstraintSet.TOP, textView.getId(),ConstraintSet.BOTTOM);
set.connect(imgId, ConstraintSet.LEFT, PARENT_ID,ConstraintSet.LEFT);
set.connect(imgId, ConstraintSet.RIGHT, PARENT_ID,ConstraintSet.RIGHT);
set.constrainWidth(imgId,ConstraintSet.MATCH_CONSTRAINT);
set.constrainHeight(imgId, ConstraintSet.WRAP_CONTENT);
set.connect(R.id.testImg, ConstraintSet.TOP, imgId , ConstraintSet.BOTTOM);
ScrollView scrollView = (ScrollView) findViewById(R.id.VVV);
scrollView.setFillViewport(true);
set.applyTo(layout);