29
loading...
This website collects cookies to deliver better user experience
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/example_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ConstraintLayout
is just a container that allows us extra customization, however, we don't actually use this customization. The xmlns:
stands for xml-namespace and it is how we define resources to certain namespaces. android
, app
and tools
are all namespaces and the URIs that they are set to equal the resources that they have access to. You can see that we set the width and height on ConstraintLayout to match_parent meaning it is set to the whole screen. The tools:context=".MainActivity"
is declaring which activity is associated with this XML file by default.android:id
so we can reference it later in our code. The layout width and height are set to match parent so it will stretch to the whole screen.<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/animalName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
Layout Resource File
. To do this go inside the resource folder and click file
--> new
--> Layout Resource File
. The file name can be whatever you want, make sure to entirely delete the default Root element
then just add LinearLayout
hit ok and you should have a new Layout Resource File
. Make sure that the android:orientation="horizontal"
is set to horizontal. This makes sure that the imbedded view is displayed horizontal. Also make sure android:layout_height="wrap_content"
I believe that the default is match_parent
, if you set it to match_parent one item will take up the entire screen. Then add a TextView, this is what is going to hold the individual item for each piece of data that we provide to the RecyclerView. We give it an android:id="@+id/animalName"
so we can reference it later for data binding. Also make sure that the layout width and height are set to wrap_content. This assures that the item is no bigger than it has to be. A TextView is just a View that is used to display text to the user. A LinearLayout is just a ViewGroup that alights all its children in a single line, either horizontally or vertically, for us its horizontally. Lets move on public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private List<String> data;
public CustomAdapter( List<String> data){
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
//this is where we inflate the recycler_view.xml
View views = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view,parent,false);
return new ViewHolder(views);
}
@Override
public void onBindViewHolder( CustomAdapter.ViewHolder holder, int position) {
String animal = this.data.get(position);
holder.myTextView.setText(animal);
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView myTextView;
public ViewHolder(View view){
super(view);
myTextView = view.findViewById(R.id.animalName);
}
}
}
extends
RecyclerView.Adapter, the extends keyword signifies that it is a subclass of the RecyclerView.Adapter class. The <CustomAdapter.ViewHolder>
is how we use generics in Java. The reason that we have to do this is because of Bounded Type Parameters. If we look at the documentation of RecyclerView.Adapter
we find this RecyclerView.Adapter<VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder>
and this is a clear example of bounded type parameters in Java. Now what this is actually saying is that it accepts any ViewHolder object or its subclass. We will see shorty that we indeed create a ViewHolder subclass. HERE is a link to the official bounded type parameters documentation.private List<String> data;
public CustomAdapter( List<String> data){
this.data = data;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView myTextView;
public ViewHolder(View view){
super(view);
myTextView = view.findViewById(R.id.animalName);
}
}
With this code block the first two things that you probably noticed was 1) it is a nested class and 2) it is static. So first lets start off with why it is nested? Well in Java you nest one class inside of another because the nested class is highly related to the outer class(which is true for us). Then comes the second question, why is it static? Well first it should be pointed out that in Java a class can only be static if it is a nested class. A nested static class can only reference other static fields from the other class. In general a static class is used to remove some dependency from the outer class. In Android we make it static to prevent memory leaks.
Before we talk the TextView
I want to talk about the super(view)
call in the constructor. Why is is there? Any time in Java when we are extending something which we are with this class, the constructor must make a super()
call of some sort. If we do not define a super() call then the Java compiler will make one for us. If you delete the super(view) from our code you will get an error that will say There is no default constructor available in ViewHolder
. This proves that when we do not define our own constructor call, Java does it for us. Why do we need this constructor call? The super() call makes sure our super class is instantiated before our own class, just incase we use any super methods or variables.
Now lets talk about the TextView
and why we are referencing it. If you are unfamiliar with TextView, it is just a View in Android that is used to display a text. We are using it because when our ViewHolder
object gets created, we want to have a reference to what we bind our data to. Later on you will see how objects created with this class get passed around the Adapter's
methods, that demonstration should give you a better understanding of why is is needed. Now what is the view.findViewById(R.id.animalName);
? The view part will be an inflated(created) view that gets passed in by the adapter(more on this late).findViewById
does exactly what it says it does, it finds a View by is id. ok but what is R.id.animalName
? 'R' stands for resources and it is an auto generated class that contains everything that can be accessed inside of our resource file. id.animalName
comes from us defining an id on our TextView when we created our individual ViewHolder object.
RecyclerView.Adapter<CustomAdapter.ViewHolder>
we have to implement 3 methods, why do we have to do this? This is because RecyclerView.Adapter is an abstract class and when we extend an abstract class we must implement all of the abstract methods. Those three methods that we have to implement are:@Override
public ViewHolder onCreateViewHolder( ViewGroup parent, int viewType) {
View views = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view,parent,false);
return new ViewHolder(views);
}
LayoutInflater
in Android.
View views = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view,parent,false);
from
is used to obtain the LayoutInflater from the current context. The current context is obtained from parent.getContext()
which the context of the RecyclerView. context
simply means the current state of the application and what resources it has access to at that current state of the Android lifecycle. Finally inflate()
is used to create the View hierarchy from the specified XML resources. Which means that our view for the individual item in the RecyclerView is finally created. R.layout.recycler_view
is the XML file that we created specifically for our individual unit in the RecyclerView. parent
is the RecyclerView and false
is to specify that we do not want to attach this view to the parent view, the RecyclerView will do that for us automatically.return new ViewHolder(views);
@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
String animal = this.data.get(position);
holder.myTextView.setText(animal);
}
CustomAdapter.ViewHolder
that is how we reference a nested class in Java by first mentioning its outer class. Then we get the data that corresponds to the current position in the data set, we are able to do that because our data is in the form of an ArrayList. Lastly we set the text on the TextView.
holder.myTextView.setText(animal);
@Override
public int getItemCount() {
return data.size();
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);// takes a layout resource file
setContentView(R.layout.activity_main); // this inflates the UI
//data to populate the data for recyclerView
ArrayList<String> data=new ArrayList<>();
for(int i = 0; i< 50;i ++){
data.add("animal # " + i);
}
// Setting the RecyclerView
RecyclerView recyclerView = findViewById(R.id.example_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new CustomAdapter(data));
}
}
extends AppCompatActivity
is just giving us access to extra features inside of the android system. Then we come to the onCreate() method, what is onCreate()? It is a method that gets called when an activity is being created. This is where most of the initialization of an Activity is going to go. It is passed a Bundle
, which is any previously saved state. We do not have any previously saved state so we don't have to worry about that. Then we have the super call super.onCreate(savedInstanceState)
. The super call is just to make sure the super class also gets instantiated. The setContentView(R.layout.activity_main)
is what the Android system uses to inflate our XML file that is associated with this activity.
ArrayList<String> data=new ArrayList<>();
for(int i = 0; i< 50;i ++){
data.add("animal # " + i);
}
"animal # " + i
where i
is the number that represents what iteration we are on.// Setting the RecyclerView
RecyclerView recyclerView = findViewById(R.id.example_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(new CustomAdapter(data));
this
which will act as the current context of the activity recyclerView.setAdapter(new CustomAdapter(data));