Android MVVM Room LiveData Full CRUD App → RecyclerView Adapter – Camposha

Android MVVM Room LiveData Full CRUD App

Android Room LiveData CRUD

RecyclerView Adapter

This is the class where we create our recyclerview adapter. This class is part of the Android Room LiveData CRUD Full App Course series. In the series we are creating a full android app using Room, LiveData and ViewModel, and basing our app design on MVVM design pattern.

Roles of Our Adapter Class

This adapter class we will create will be responsible for the following roles:

  1. Inflate our model layout into a View object.
  2. Bind data to the inflated view widgets.
  3. Hold inflated views for recycling using an inner RecyclerView.ViewHolder class.

Thus it’s mandatory for us since our next lesson involve us loading data to the recyclerview.

Video Lesson

Step 1: Create a Layout File

(a). model.xml

This layout file will be inflated into custom View objects using the LayoutInflater class:

        View view = LayoutInflater.from(c).inflate(R.layout.model, parent, false);

That view will then be passed to the ViewHolder from where it will be used to reference widgets that were defined in the layout:

            nameTxt = itemView.findViewById(R.id.mNameTxt);

Add the following XML code in the model.xml file:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="140dp"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_margin="5dp"
    android:orientation="horizontal"
    card_view:cardCornerRadius="5dp"
    card_view:cardElevation="5dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.github.ivbaranov.mli.MaterialLetterIcon
            android:id="@+id/mMaterialLetterIcon"
            android:layout_width="@dimen/list_item_avatar_size"
            android:layout_height="@dimen/list_item_avatar_size"
            android:layout_marginRight="8dp" />

        <TextView
            android:id="@+id/mNameTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toRightOf="@+id/mMaterialLetterIcon"
            android:padding="3dp"
            android:text="Scientist's Name"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:textColor="#009968" />

        <TextView
            android:id="@+id/mDescriptionTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/mMaterialLetterIcon"
            android:maxLines="2"
            android:layout_below="@id/mNameTxt"
            android:text="Scientists Description"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textStyle="italic" />

        <TextView
            android:id="@+id/mGalaxyTxt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="Galaxy"
            android:textColor="@color/colorAccent"
            android:textStyle="italic"
            fontPath="fonts/RobotoCondensed-Regular.ttf"
            android:textAppearance="?android:attr/textAppearanceSmall"
            tools:ignore="MissingPrefix"/>

    </RelativeLayout>
</androidx.cardview.widget.CardView>

Step 2: Create Adapter Class

(a). MyAdapter.java

This is the adapter class we have talked about.

Start by creating a file called MyAdapter.java, then adding the imports:

package info.camposha.roomlivedatacrudapp.view.adapter;

import android.content.Context;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.github.ivbaranov.mli.MaterialLetterIcon;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import info.camposha.roomlivedatacrudapp.R;
import info.camposha.roomlivedatacrudapp.data.model.Scientist;
import info.camposha.roomlivedatacrudapp.common.Utils;
import info.camposha.roomlivedatacrudapp.view.ui.DetailActivity;

Then define the class, making it derive from RecyclerView.Adapter:

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

Then add our final instance fields:

    private final Context c;
    private final int mBackground;
    private final int[] mMaterialColors;
    private final List<Scientist> scientists;

Then create an inner ViewHolder class:

    public class ViewHolder extends RecyclerView.ViewHolder implements
     View.OnClickListener {
        private final TextView nameTxt;
        private final TextView mDescriptionTxt;
        private final TextView galaxyTxt;
        private final MaterialLetterIcon mIcon;
        private ItemClickListener itemClickListener;

The ViewHolder class as you can see defines final instance fields which will be used to hold our View objects. This saves our app from having to re-inflate the same layout over and over for different rows. This leads to massive performance gains.

Then initialize those widgets:

        ViewHolder(View itemView) {
            super(itemView);
            mIcon = itemView.findViewById(R.id.mMaterialLetterIcon);
            nameTxt = itemView.findViewById(R.id.mNameTxt);
            mDescriptionTxt = itemView.findViewById(R.id.mDescriptionTxt);
            galaxyTxt = itemView.findViewById(R.id.mGalaxyTxt);
            itemView.setOnClickListener(this);
        }

As you can see we’ve referenced them inside the constructor using the passed View object.

Then code for our onClicks:

        @Override
        public void onClick(View view) {
            this.itemClickListener.onItemClick(this.getLayoutPosition());
        }

        void setItemClickListener(ItemClickListener itemClickListener) {
            this.itemClickListener = itemClickListener;
        }
    }

Full Code

package info.camposha.roomlivedatacrudapp.view.adapter;
import android.content.Context;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.github.ivbaranov.mli.MaterialLetterIcon;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import info.camposha.roomlivedatacrudapp.R;
import info.camposha.roomlivedatacrudapp.data.model.Scientist;
import info.camposha.roomlivedatacrudapp.common.Utils;
import info.camposha.roomlivedatacrudapp.view.ui.DetailActivity;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private final Context c;
private final int mBackground;
private final int[] mMaterialColors;
private final List<Scientist> scientists;
public class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
private final TextView nameTxt;
private final TextView mDescriptionTxt;
private final TextView galaxyTxt;
private final MaterialLetterIcon mIcon;
private ItemClickListener itemClickListener;
ViewHolder(View itemView) {
super(itemView);
mIcon = itemView.findViewById(R.id.mMaterialLetterIcon);
nameTxt = itemView.findViewById(R.id.mNameTxt);
mDescriptionTxt = itemView.findViewById(R.id.mDescriptionTxt);
galaxyTxt = itemView.findViewById(R.id.mGalaxyTxt);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
this.itemClickListener.onItemClick(this.getLayoutPosition());
}
void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
}
public MyAdapter(Context mContext, ArrayList<Scientist> scientists) {
this.c = mContext;
this.scientists = scientists;
TypedValue mTypedValue = new TypedValue();
c.getTheme().resolveAttribute(R.attr.selectableItemBackground,
mTypedValue, true);
mMaterialColors = c.getResources().getIntArray(R.array.colors);
mBackground = mTypedValue.resourceId;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(c).inflate(R.layout.model, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
//get current scientist
final Scientist s = scientists.get(position);
//bind data to widgets
holder.nameTxt.setText(s.getName());
holder.mDescriptionTxt.setText(s.getDescription());
holder.galaxyTxt.setText(s.getGalaxy());
holder.mIcon.setInitials(true);
holder.mIcon.setInitialsNumber(2);
holder.mIcon.setLetterSize(25);
holder.mIcon.setShapeColor(mMaterialColors[new Random().nextInt(
mMaterialColors.length)]);
holder.mIcon.setLetter(s.getName());
//open detailactivity when clicked
holder.setItemClickListener(pos -> Utils.sendScientistToActivity(c, s,
DetailActivity.class));
}
@Override
public int getItemCount() {
return scientists.size();
}
interface ItemClickListener {
void onItemClick(int pos);
}
}
//end

Now move over to the next lesson to continue with the course.

Leave a Reply

Your email address will not be published. Required fields are marked *

X