About RecyclerView.ViewHolder and RecyclerView.Adapter

24,902

Solution 1

Doesn’t the final modifier indicate that the value of this field cannot change ?

The final modifier on a View indicate that you can only initiate the view once (by creating a new View(context) or inflate a view from an xml file). But you can still modify the view property. (i.e. your view contains a TextView, you can set the text)

For your second question, the text book is not very precise about how to implement the adapter with a view holder. Here is a simple implementation of an adapter with a custom view holder.

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);
        }
    }

}

and the xml file for it:

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

You can see that if you extend RecyclerView.Adapter, you will have to override these 3 methods.

Hope this will help you to understand more the RecyclerView.

Solution 2

1 :- Main Layout

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

2:- items layout

<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 items

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 Adapter class

 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();
}

}

Share:
24,902
Admin
Author by

Admin

Updated on August 15, 2020

Comments

  • Admin
    Admin almost 4 years
    1. The RecyclerView.ViewHolder class has a field that is public final View itemView. It says that the onBindViewHolder method should update the contents of the itemView to reflect the item at the given position . Doesn’t the final modifier indicate that the value of this field cannot change ?

    2. The code below is from the textbook :

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

      Why do these methods here can override the methods in the RecyclerView.Adapter class which is derived from the RecyclerView.ViewHolder class ?

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

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

    Could someone explain it ?

    Thank you.

  • Admin
    Admin almost 9 years
    Does android.support.v7.widget.RecyclerView.Adapter<VH extends android.support.v7.widget.RecyclerView.ViewHolder> mean that RecyclerView.Adapter class is the subclass derived from the RecyclerView.ViewHolder class ? I ran the code from the textbook, and didn't get an error ...
  • hrss
    hrss almost 9 years
    I don't think so. It means it receives a parameter VH that is a subclass of ViewHolder.
  • Admin
    Admin almost 9 years
    In another place, it says "RecyclerView.Adapter implementations should subclass ViewHolder" (from developer.android.com/reference/android/support/v7/widget/…)‌​. What does it actually mean ?
  • hrss
    hrss almost 9 years
    And, did you actually make this code runnable? like putting some real stuff instead of "..."? I had to make some changes before i got the errors.
  • hrss
    hrss almost 9 years
    I think it means creating a ViewHolder class that extends RecyclerView.ViewHolder inside the adapter, like in xiaomi's answer.
  • Admin
    Admin almost 9 years
    Could I ask why it should append <Adapter.MyViewHolder> to RecyclerView.Adapter and why the class name can be named Adapter which is already in developer.android.com/reference/android/widget/Adapter.html ?
  • xiaomi
    xiaomi almost 9 years
    I edit my post. The name of this class can by MyAdapter or whatever you want. There is no relation with the widget Adapter you linked. The method onCreateViewHolder should return a custom view holder which extends RecyclerView.ViewHolder.
  • Admin
    Admin almost 9 years
    If the name of this class is MyAdapter, should RecyclerView.Adapter<Adapter.MyViewHolder> be changed to RecyclerView.Adapter<MyAdapter.MyViewHolder> ?
  • Admin
    Admin almost 9 years
    For the first question, do you mean if I set The final modifier on a View, I can't change the view which has been initiated, but I still modify the view property ?
  • Admin
    Admin almost 9 years
    I read the code again, and found that it is just like xiaomi's answer. the methods should be put in public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>, and what I write above is incorrect.
  • xiaomi
    xiaomi almost 9 years
    Yes, the final initiate the object, but you can modify the property of this object. if You use final View view = new View(context), later you won't be able to to view = null or view = new View(null)
  • Admin
    Admin almost 9 years
    Could I also ask "I learned that paper in material design cannot be flipped over, but I found that like Flipping CardView in RecyclerView I want to ask whether my knowledge is correct." ? Thank you.
  • xiaomi
    xiaomi almost 9 years
    You can do what you want, the guideline for the design is a "what you should do" but not a "what you must do".
  • maniaq
    maniaq over 4 years
    This answer was complete but if you want to implement an onclick listener for a floatingactionbutton , this setOnClickListener method must be inset in which methods: onBind... or in the Custom MyViewHolder ?