About RecyclerView.ViewHolder and RecyclerView.Adapter
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();
}
}
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on August 15, 2020Comments
-
Admin almost 4 years
The
RecyclerView.ViewHolder
class has a field that ispublic final View itemView
. It says that theonBindViewHolder
method should update the contents of theitemView
to reflect the item at the given position . Doesn’t thefinal
modifier indicate that the value of this field cannot change ?-
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 theRecyclerView.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 almost 9 yearsDoes
android.support.v7.widget.RecyclerView.Adapter<VH extends android.support.v7.widget.RecyclerView.ViewHolder>
mean thatRecyclerView.Adapter
class is the subclass derived from theRecyclerView.ViewHolder
class ? I ran the code from the textbook, and didn't get an error ... -
hrss almost 9 yearsI don't think so. It means it receives a parameter VH that is a subclass of ViewHolder.
-
Admin almost 9 yearsIn 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 almost 9 yearsAnd, 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 almost 9 yearsI think it means creating a ViewHolder class that extends RecyclerView.ViewHolder inside the adapter, like in xiaomi's answer.
-
Admin almost 9 yearsCould I ask why it should append
<Adapter.MyViewHolder>
toRecyclerView.Adapter
and why the class name can be namedAdapter
which is already in developer.android.com/reference/android/widget/Adapter.html ? -
xiaomi almost 9 yearsI 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 almost 9 yearsIf the name of this class is
MyAdapter
, shouldRecyclerView.Adapter<Adapter.MyViewHolder>
be changed toRecyclerView.Adapter<MyAdapter.MyViewHolder>
? -
Admin almost 9 yearsFor 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 almost 9 yearsI 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 almost 9 yearsYes, 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 toview = null
orview = new View(null)
-
Admin almost 9 yearsCould 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 almost 9 yearsYou can do what you want, the guideline for the design is a "what you should do" but not a "what you must do".
-
maniaq over 4 yearsThis 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 ?