处理RecyclerView列表项时使用继承是否为反模式?

时间:2017-11-23 14:03:43

标签: java android android-recyclerview recycler-adapter

我想将两个类混合并匹配到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.
    }
}

2 个答案:

答案 0 :(得分:1)

我个人认为这不是反模式。对于那些场景,我已经实现了一个名为委托适配器的模式,这是对this文章(推荐讲座)的概念的修改。

我建议您对当前的实施进行一些修改:

  • BaseItem中指定一个声明其视图类型的抽象方法,并让它们实现所述方法。像getViewType之类的东西可以避免令人讨厌的getClass比较。
  • 将您注册的视图类型存储在实用程序类中,或者更好地将IntDef定义存储在更清晰的代码中。

答案 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);