简体   繁体   English

在处理 RecyclerView 列表项时使用继承是一种反模式吗?

[英]Is it an anti-pattern to use inheritance when handling RecyclerView list items?

I have two classes I want to mix and match into a recyclerView, ItemA and ItemB.我有两个类我想混合和匹配到一个 recyclerView,ItemA 和 ItemB。 In order to do this I've given them a base class of BaseItem so they can be passed in as one List.为了做到这一点,我给了他们一个 BaseItem 的基类,这样他们就可以作为一个 List 传入。 Then in my RecyclerAdapter's getItemViewType method I work out what the class is so I can use the correct Viewholder.然后在我的 RecyclerAdapter 的 getItemViewType 方法中,我计算出类是什么,以便我可以使用正确的 Viewholder。

At this point my internal anti-pattern instincts started flaring up.在这一点上,我内心的反模式本能开始燃烧起来。 I generally feel that if you have to work out what the concrete class is to handle an object then it shouldn't have a base class.我通常认为,如果您必须弄清楚处理对象的具体类是什么,那么它就不应该有基类。 Is this the wrong way to go about doing this?这是错误的做法吗? I've been unable to find any examples of people doing similarly.我一直无法找到任何类似的人的例子。

Is there a good alternative to this?有什么好的替代方法吗? I put together some code to illustrate my point.我整理了一些代码来说明我的观点。

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

I personally do not consider it an anti pattern.我个人不认为这是一种反模式。 For those scenarios Ive implemented a pattern called delegate adapter which is a modification from an idea of this article (lecture recommended).对于这些场景,我实现了一种称为委托适配器的模式,这是对本文思想的修改(推荐讲座)。

I do recommend though some modifications to your current implementation:我确实建议对您当前的实现进行一些修改:

  • Specify an abstract method in BaseItem that declares its view type, and let it children implement said method.BaseItem中指定一个声明其视图类型的抽象方法,并让它子项实现该方法。 Something like getViewType that way you avoid the nasty getClass comparison.getViewType这样的东西,你可以避免讨厌的getClass比较。
  • Store your registered view types in a utility class or even better a IntDef definition for clearer code.将您注册的视图类型存储在实用程序类中,或者甚至更好的 IntDef 定义中,以便更清晰的代码。

M personal opinion, is that it would be considered an anti-pattern if those two models have no logical relationship, hence not sharing any common attributes, or cannot be expressed with an abstraction.我个人的看法是,如果这两个模型没有逻辑关系,因此没有共享任何共同属性,或者不能用抽象来表达,那么它会被认为是反模式。

If your only goal is to only pass in a list containing both models, pass a List<Object>如果您的唯一目标是只传入包含两个模型的List<Object> ,请传递List<Object>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM