关于RecyclerView.ViewHolder和RecyclerView.Adapter

时间:2015-09-06 00:38:40

标签: android android-5.0-lollipop android-recyclerview android-viewholder

  1. RecyclerView.ViewHolder类的字段为public final View itemView。它表示onBindViewHolder方法应更新itemView的内容以反映给定位置的项目。 final修饰符是否表示此字段的值不能更改?

  2. 以下代码来自教科书:

    public class ViewHolder extends RecyclerView.ViewHolder {
       ...
          @Override
          public int getItemCount() {
              ...
          }
          @Override
          public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int    viewType) {
             ...
          }
          @Override
          public void onBindViewHolder(ViewHolder viewHolder, int position) {
             ...
          }
    }
    

    为什么这里的这些方法可以覆盖从RecyclerView.Adapter类派生的RecyclerView.ViewHolder类中的方法?

  3. https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html

    https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder.html

    有人可以解释一下吗?

    谢谢。

3 个答案:

答案 0 :(得分:10)

  

最终修饰符是否表示此字段的值   不能改变?

View上的最终修饰符表示您可以启动一次视图(通过创建新的View(上下文)或从xml文件中扩展视图)。 但您仍然可以修改视图属性。 (即您的视图包含TextView,您可以设置文本)

对于第二个问题,教科书对于如何使用视图持有者实现适配器并不十分精确。这是一个带有自定义视图持有者的适配器的简单实现。

public class Adapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{

    private List<String> titles;

    public Adapter(List<String> titles) {
        this.titles = titles;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        return new MyViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_view, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(MyViewHolder myViewHolder, int i) {
        String title = titles.get(i);
        myViewHolder.title.setText(title);
    }

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

    public static class MyViewHolder extends RecyclerView.ViewHolder {

        TextView title;

        public MyViewHolder(View itemView) {
            super(itemView);

            title = (TextView) itemView.findViewById(R.id.title_TV);
        }
    }

}

和它的xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <TextView
        android:id="@+id/title_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

您可以看到,如果扩展RecyclerView.Adapter,则必须覆盖这3种方法。

希望这有助于您了解更多RecyclerView。

答案 1 :(得分:3)

1: - 主要布局

    <android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="vertical" />

2: - 项目布局

<TextView
    android:id="@+id/title"
    android:textColor="#000000"
    android:textSize="16dp"
    android:textStyle="bold"
    android:layout_alignParentTop="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/genre"
    android:layout_below="@id/title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/year"
    android:textColor="#000FFF"
    android:layout_width="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_height="wrap_content" />

3: - MainActivity

 private List<Movie> movieList = new ArrayList<>();
 private RecyclerView recyclerView;
 private MoviesAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.moviemainlayout);



    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    mAdapter = new MoviesAdapter(movieList);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(mAdapter);

    prepareMovieData();
}

private void prepareMovieData() {
    Movie movie = new Movie("Mad Max: Fury Road", "Action & Adventure", "2015");
    movieList.add(movie);

    movie = new Movie("Inside Out", "Animation, Kids & Family", "2015");
    movieList.add(movie);

    movie = new Movie("Star Wars: Episode VII - The Force Awakens", "Action", "2015");
    movieList.add(movie);

    movie = new Movie("Shaun the Sheep", "Animation", "2015");
    movieList.add(movie);

    movie = new Movie("The Martian", "Science Fiction & Fantasy", "2015");
    movieList.add(movie);

    movie = new Movie("Mission: Impossible Rogue Nation", "Action", "2015");
    movieList.add(movie);

    movie = new Movie("Up", "Animation", "2009");
    movieList.add(movie);

    movie = new Movie("Star Trek", "Science Fiction", "2009");
    movieList.add(movie);

    movie = new Movie("The LEGO Movie", "Animation", "2014");
    movieList.add(movie);

    movie = new Movie("Iron Man", "Action & Adventure", "2008");
    movieList.add(movie);

    movie = new Movie("Aliens", "Science Fiction", "1986");
    movieList.add(movie);

    movie = new Movie("Chicken Run", "Animation", "2000");
    movieList.add(movie);

    movie = new Movie("Back to the Future", "Science Fiction", "1985");
    movieList.add(movie);

    movie = new Movie("Raiders of the Lost Ark", "Action & Adventure", "1981");
    movieList.add(movie);

    movie = new Movie("Goldfinger", "Action & Adventure", "1965");
    movieList.add(movie);

    movie = new Movie("Guardians of the Galaxy", "Science Fiction & Fantasy", "2014");
    movieList.add(movie);

    mAdapter.notifyDataSetChanged();
}

}

ModelClass项目

public class Movie {
private String title, genre, year;

public Movie() {
}

public Movie(String title, String genre, String year) {
    this.title = title;
    this.genre = genre;
    this.year = year;
}

public String getTitle() {
    return title;
}

public void setTitle(String name) {
    this.title = name;
}

public String getYear() {
    return year;
}

public void setYear(String year) {
    this.year = year;
}

public String getGenre() {
    return genre;
}

public void setGenre(String genre) {
    this.genre = genre;
}

}

3适配器类

 public class MoviesAdapter extends 
   RecyclerView.Adapter<MoviesAdapter.MyViewHolder> {

private List<Movie> moviesList;

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title, year, genre;

    public MyViewHolder(View view) {
        super(view);
        title = (TextView) view.findViewById(R.id.title);
        genre = (TextView) view.findViewById(R.id.genre);
        year = (TextView) view.findViewById(R.id.year);
    }
}


public MoviesAdapter(List<Movie> moviesList) {
    this.moviesList = moviesList;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.movie_list_row, parent, false);

    return new MyViewHolder(itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    Movie movie = moviesList.get(position);
    holder.title.setText(movie.getTitle());
    holder.genre.setText(movie.getGenre());
    holder.year.setText(movie.getYear());
}

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

}

答案 2 :(得分:0)

final修饰符意味着您不能将另一个对象分配给该指针或引用,但是您仍然可以更改原始对象的内部值,例如任何公共属性或任何其他对象,前提是getter和setter。在这里编辑,我试图重新创建你在android studio上给我们的代码,它告诉我“方法不会覆盖它的超类方法”。除此之外,我收到一个错误,因为超类没有默认构造函数。所以,我不认为教科书是对的。