简体   繁体   English

什么是 RecyclerView.Adapter<MyAdapter.MyViewHolder> 以及它与 Android 中的 RecyclerView.Adapter 有何不同?

[英]What is RecyclerView.Adapter<MyAdapter.MyViewHolder> and how it is different from RecyclerView.Adapter in Android?

I'm learning RecyclerView and in developer 's site the Adapter class extends RecyclerView.Adapter<MyAdapter.MyViewHolder> .我正在学习 RecyclerView 并且在开发人员的站点中, Adapter 类扩展了RecyclerView.Adapter<MyAdapter.MyViewHolder> The implementation shows:实现显示:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;


public static class MyViewHolder extends RecyclerView.ViewHolder {

    public TextView textView;
    public MyViewHolder(TextView v) {
        super(v);
        textView = v;
    }
}

public MyAdapter(String[] myDataset) {
    mDataset = myDataset;
}

@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {

    TextView v = (TextView) LayoutInflater.from(parent.getContext())
            .inflate(R.layout.my_text_view, parent, false);

    MyViewHolder vh = new MyViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {

    holder.textView.setText(mDataset[position]);

}

@Override
public int getItemCount() {
    return mDataset.length;
}
}

And in this tutorial , the adapter class extends RecyclerView.Adapter .在本教程中,适配器类扩展了RecyclerView.Adapter The implementation is:实现是:

public class SimpleAdapter extends RecyclerView.Adapter {

private List<SimpleViewModel> models = new ArrayList<>();


public SimpleAdapter(final List<SimpleViewModel> viewModels) {
    if (viewModels != null) {
        this.models.addAll(viewModels);
    }
}


@Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
    return new SimpleViewHolder(view);
}


@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    ((SimpleViewHolder) holder).bindData(models.get(position));
}


@Override
public int getItemCount() {
    return models.size();
}


@Override
public int getItemViewType(final int position) {
    return R.layout.item_simple_itemview;
}
}

So what is the difference between RecyclerView.Adapter<MyAdapter.MyViewHolder> and RecyclerView.Adapter and what is the syntax<> in RecyclerView.Adapter<MyAdapter.MyViewHolder> means in this case?那么RecyclerView.Adapter<MyAdapter.MyViewHolder>RecyclerView.Adapter什么RecyclerView.Adapter<MyAdapter.MyViewHolder>在这种情况下RecyclerView.Adapter<MyAdapter.MyViewHolder>的语法<>是什么意思? I know it stands for generics.我知道它代表泛型。 When should I use this?我应该什么时候使用它?

So what is the difference between RecyclerView.Adapter< MyAdapter.MyViewHolder> and RecyclerView.Adapter and what is the syntax<> in RecyclerView.Adapter means in this case?那么 RecyclerView.Adapter< MyAdapter.MyViewHolder> 和 RecyclerView.Adapter 之间有什么区别,在这种情况下 RecyclerView.Adapter 中的语法<>是什么意思? I know it stands for generics.我知道它代表泛型。 When should I use this?我应该什么时候使用它?

First, let's review the definition of the Adapter class.首先,让我们回顾一下Adapter类的定义。 It's defined within RecyclerView as so:它在RecyclerView定义如下:

public abstract static class Adapter<VH extends ViewHolder>

So what does the "generics" part of this mean?那么这里的“泛型”部分是什么意思呢? It means the Adapter class operates on some class type ( VH ) that must be a descendant of the class ViewHolder .这意味着 Adapter 类对某些类类型 ( VH ) 进行操作,该类类型必须是类ViewHolder的后代。 This is known as a Bounded Type and ensures that the type of of class the adapter is working with is guaranteed to be a type of ViewHolder .这被称为有界类型,并确保适配器正在使用的类的类型保证是ViewHolder的类型。

As you see with the example on the developer's site you posted, when you create your own adapter that specifies the type of the ViewHolder as MyViewHolder , then the methods you have to override in the adapter explicitly declare that type in their signatures.正如您在您发布的开发人员网站上的示例中看到的那样,当您创建自己的适配器并将 ViewHolder 的类型指定为MyViewHolder ,您必须在适配器中覆盖的方法在其签名中显式声明该类型。 For example, the return type for onCreateViewHolder is explicitly set to MyViewHolder .例如, onCreateViewHolder的返回类型明确设置为MyViewHolder

@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {

    TextView v = (TextView) LayoutInflater.from(parent.getContext())
            .inflate(R.layout.my_text_view, parent, false);

    MyViewHolder vh = new MyViewHolder(v);
    return vh;
}

Alternatively, the tutorial you posted does not specify a type.或者,您发布的教程指定类型。

public class SimpleAdapter extends RecyclerView.Adapter

When you extend a class that expects a generic type and don't specify one, the compiler defaults to the least common denominator - that is, the class type lowest in the inheritance hierarchy that will guarantee the class can be used as designed.当您扩展一个需要泛型类型但未指定泛型类型的类时,编译器默认为最小公分母- 即继承层次结构中最低的类类型,它将保证该类可以按设计使用。 Because the Adapter's generic type is defined as VH extends ViewHolder , the compiler knows that the class type must be at least a ViewHolder and defaults to that.因为 Adapter 的泛型类型被定义为VH extends ViewHolder ,编译器知道类类型必须至少是一个ViewHolder并且默认为它。 Hence, the same method overriden for this example returns RecyclerView.ViewHolder instead of MyViewHolder :因此,本示例重写的相同方法返回RecyclerView.ViewHolder而不是MyViewHolder

@Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
    return new SimpleViewHolder(view);
}

If RecyclerView.Adapter was defined as Adapter<VH> (no bounded type), and you extended it without specifying the type, the type would default to Object (the root class of all Java classes):如果RecyclerView.Adapter被定义为Adapter<VH> (无界类型),并且你在没有指定类型的情况下扩展它,类型将默认为Object (所有 Java 类的根类):

@Override
public Object onCreateViewHolder(final ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
    return new SimpleViewHolder(view);
}

So, finally, why use one instead of the other?那么,最后,为什么要使用一个而不是另一个呢? Generally speaking: you should always specify the type for a generic class .一般来说:您应该始终为泛型类指定类型 This guarantees you type-safety.这保证了你的类型安全。 In the tutorial example, you could return the wrong type of view holder which would compile but crash at runtime:在教程示例中,您可能会返回错误类型的视图持有者,该类型会编译但在运行时崩溃:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);

    // Returning wrong view holder, but because it still extends ViewHolder and
    // that is all this method requires, this compiles
    return new SomeOtherViewHolder(view);
}


@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    // Above we created a SomeOtherViewHolder but here we're expecting a SimpleViewHolder
    // This will crash trying to cast to the wrong type
    ((SimpleViewHolder) holder).bindData(models.get(position));
}

It's impossible to make this mistake in the first example though because the ViewHolder type is declared explicitly:在第一个例子中不可能犯这个错误,因为ViewHolder类型是显式声明的:

@Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {

    TextView v = (TextView) LayoutInflater.from(parent.getContext())
            .inflate(R.layout.my_text_view, parent, false);

    // Trying to return SomeOtherViewHolder when method expects MyViewHolder
    // Compiler's like (*waves finger*) "nuh-uh, not on my watch" and fails
    // to compile
    SomeOtherViewHolder vh = new SomeOtherViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    // Notice here that holder is explicitly of MyViewHolder type and casting
    // is not necessary! That's TYPE SAFETY y'all.
    holder.textView.setText(mDataset[position]);
}

Because you specify the explicit , concrete type you expect, you cannot accidentally return the wrong type, you do not need to cast, and you can leverage all of the public methods defined in your custom ViewHolder class.因为您指定了您期望的显式具体类型,所以您不会意外返回错误的类型,您不需要ViewHolder ,并且您可以利用自定义ViewHolder类中定义的所有公共方法。

Hope that helps!希望有帮助!

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

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