room relationship between entities

Room Database Entities Relationships

In this article we will firstly discuss what is Room database entities relationships. Also, what are the types of relationships between entities. After that, we will apply the most common relationship in our to do list app. As, we will learn how to add sub items for each item created in the To-Do list app. Moreover we will use Nested RecyclerView to show the horizontal sub items.

In the linked article below, we learned how to create simple to do list app using Room Database. Also, we learned how to migrate Room Database to save users data after database upgrade. Moreover, we learned in depth how to query information through Dao.

1- Room Database with Simple ToDo List App Android Studio.

2- Room Database Migration Android Studio.

3- Room Database Queries Using DAO.

Create embedded objects

Room Database enables us to create embedded objects. As, sometimes we need to express an objects as a cohesive whole in our database logic even if the object contains several fields. So, we can do that by using @Embedded annotation.

The following example shows how to embed Address object in the User class as field type of Address class. The table representing a User object then contains columns with the following names (id, firstName, street, state, city, and post_code).

public class Address {
    public String street;
    public String state;
    public String city;

    @ColumnInfo(name = "post_code") public int postCode;
}

@Entity
public class User {
    @PrimaryKey public int id;

    public String firstName;

    @Embedded public Address address;
}

Define one-to-one relationships

This type of Room Database Entities Relationships is less common. Moreover, it is a relationship where each instance of the parent entity corresponds to exactly one instance of the child entity and vice versa.

For example, a music streaming app where each user has his own library. Moreover, each user has only one library and each library corresponds to only one user. Therefore, there should be one to one relationship between the User entity and Library entity.

In order to create this type of relationship, create two classes for the two entities. one should be the parent (User) entity and the other is the child (Library). Furthermore, the later should contain the variable that is a reference to the primary key of the other entity. The following example shows how to create that.

room database one to one relationship
@Entity
public class User {
    @PrimaryKey 
    @ColumnInfo(name = "userId")
    public long userId;

    @ColumnInfo(name = "name")
    public String name; 
    @ColumnInfo(name = "age")
    public int age;
}

@Entity(tableName = "libraries",foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "userId",
childColumns = "userOwnerId",onDelete = CASCADE))
public class Library {
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "libraryId")
    public long libraryId;
    @ColumnInfo(name = "userOwnerId")
    public long userOwnerId;
}

In order to query the list of users and their corresponding libraries, we must first to model class for one to one relationship between the two entities. So that, create a new data class where each instance holds an instance of the parent entity and the corresponding instance of the child entity. Also, use @Relation annotation for child entity. Use the following code.

public class UserAndLibrary {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    public Library library;
}

Finally, add a method to the DAO class that returns all instances of the data class that pairs the parent entity and the child entity. Moreover, this method requires Room to run two queries. So, add the @Transaction annotation to this method to ensure that the whole operation is performed atomically.

@Transaction
@Query("SELECT * FROM User")
public List<UserAndLibrary> getUsersAndLibraries();

Define one to many relationships

Another type of Room Database Entities Relationships. It is the relationship between two entities, where each instance of parent entity corresponds to zero or more instances of child entity. But each instance of child entity corresponds to only one instance of the parent entity.

For example, in the music streaming app each user may have one or more playlist to organize his songs in playlists. Moreover, each user can create more than playlist, but each playlist should be created by only one user. In order to create one to many relationships, we need to create two entities. Firstly, one for User which considered as the parent entity. Secondly, one will be the Playlist entity and considered as child one. Also the child entity should contain the variable that is a reference to the primary key of the other entity. The following example shows how to create that.

@Entity
public class User {
    @PrimaryKey 
    @ColumnInfo(name = "userId")
    public long userId;

    @ColumnInfo(name = "name")
    public String name; 
    @ColumnInfo(name = "age")
    public int age;
}

@Entity(tableName = "playlists",foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "userId",
childColumns = "userOwnerId",onDelete = CASCADE))
public class Playlist{
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "playlistId")
    public long libraryId;
    @ColumnInfo(name = "userOwnerId")
    public long userOwnerId;
}

To make query for one to many relationship, create a new data class that models the two entities. Differently, each instance of parent entity hold a list of child entities.

public class UserAndPlaylists {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    public List<Playlist> playlists;
}

Finally, in DAO use the following to select all users with their playlists.

@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylists> getUsersWithPlaylists();

Adding Sub-Items to To-Do List App Android Studio

Lets start practically to study the most common type of Room Relational Database, which is one to many relationship. For that, we will work on the previously created To-Do List App to add sub-items to each created item. Furthermore, you can use above three links to copy the source code and start to add the following code.

Items Row Layout File

First, we need to update the items row layout file (to_do_list_item.xml file) to add a recyclerview that holds the sub-items in a horizontal manner. As,you can copy the following code in the file. Also, we need to add a new button to add the new sub items.

items row layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_margin="3dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="10dp"
app:cardCornerRadius="5dp"
app:cardBackgroundColor="@color/colorAccent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toDoItem"
android:textColor="@android:color/black"
android:textStyle="bold"
android:textSize="20dp"
android:text="To Do Item"
android:padding="8dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toDoDate"
android:textColor="@android:color/black"
android:textSize="14dp"
android:text="To Do Date"
android:padding="8dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/toDoTime"
android:textColor="@android:color/black"
android:textSize="12dp"
android:text="To Do Time"
android:padding="8dp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@android:color/white">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/subItemRV"/>
</FrameLayout>


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@android:color/white"
android:layout_weight="1">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Edit"
android:id="@+id/edit"
android:textAllCaps="false"
android:textColor="@android:color/black"
android:background="?attr/selectableItemBackground"
/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@android:color/white"
android:layout_weight="1">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Delete"
android:textAllCaps="false"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:id="@+id/delete"
/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@android:color/white"
android:layout_weight="1">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Sub Item"
android:textAllCaps="false"
android:background="?attr/selectableItemBackground"
android:textColor="@android:color/black"
android:id="@+id/subItem"
/>
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_gravity="center"
android:background="@android:color/white"
android:textColor="@color/colorAccent"
android:layout_weight="1">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Complete"
android:id="@+id/complete"/>
</FrameLayout>




</LinearLayout>

</LinearLayout>

</androidx.cardview.widget.CardView>

</LinearLayout>

Add New Sub-Items XML layout files

Next, we need to create a new resource layout file for adding the sub items. furthermore, when the user clicks on add new item button this layout should be appears with edit text and button to save the sub items.

new sub item row layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/subItemEditTxt"
android:layout_margin="10dp"
android:hint="Sub Item Here" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Add Sub Item"
android:id="@+id/addSubItem"/>

</LinearLayout>

Sub item Row layout File

This layout is used to show the sub items text. Simply, it is card view contains text view and it will used in the SubItemsRecyclerAdapter Class.

sub items row layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="5dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="8dp"
app:cardElevation="10dp"
app:cardBackgroundColor="@color/colorAccent">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/subItem"
android:gravity="center"
android:text="sub item"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold"/>
</androidx.cardview.widget.CardView>
</FrameLayout>

SubItems Entity Java Class

The next step is creating a new Java Class with name “SubItems” for SubItems Entitry. As following code.

@Entity(tableName = "sub_items",foreignKeys = @ForeignKey(entity = ToDoTable.class,
parentColumns = "id",
childColumns = "id",onDelete = CASCADE))
public class SubItems {

@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "subItemId")
public long subItemId;
@ColumnInfo(name = "id")
public long id;
@ColumnInfo(name = "sub_item")
public String subItemName;

public long getSubItemId() {
return subItemId;
}

public void setSubItemId(long subItemId) {
this.subItemId = subItemId;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getSubItemName() {
return subItemName;
}

public void setSubItemName(String subItemName) {
this.subItemName = subItemName;
}
}

Next, we need to create a new data class to model the entity of to_do_table entity and list of SubItems entity to create one to many relationship.

public class ItemsOneManyRelation {
    @Embedded public ToDoTable toDoTable;
    @Relation(parentColumn = "id",entityColumn = "id") public List<SubItems> subItems;

   
}

Next, Update the MyRoomDatabase class by adding SubItems class entity into entities list. then upgrade the database version.

@Database(entities = {ToDoTable.class,SubItems.class},version = 3, exportSchema = false)
public abstract class MyRoomDatabase extends RoomDatabase {

public abstract MyDaoInterface myDaoInterface();
public static MyRoomDatabase mInstance;

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {

/* database.execSQL("CREATE TABLE new_to_Do_table (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"item TEXT," +"date INTEGER, "+"time INTEGER, "+
"completed INTEGER DEFAULT 0, "+
"item_importance TEXT NOT NULL DEFAULT 'Low')");
database.execSQL("INSERT INTO new_to_Do_table (id, item, date, time, completed) " +
"SELECT id, item, date, time, completed FROM to_Do_table");
database.execSQL("DROP TABLE to_Do_table");
database.execSQL("ALTER TABLE new_to_Do_table RENAME TO to_Do_table");*/
database.execSQL("ALTER TABLE to_Do_table "
+ " ADD COLUMN item_importance TEXT");
}
};
public static MyRoomDatabase getInstance(Context context){
if (mInstance == null){
mInstance = Room.databaseBuilder(context,MyRoomDatabase.class,"MyDatabaseName")
// .addMigrations(MIGRATION_1_2)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build();
}

return mInstance;
}

}

After that in the Dao interface add the query that return the list of to_do_items with it’s sub items.

@Dao
public interface MyDaoInterface {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(ToDoTable toDoTable);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertSubItem(SubItems subItems);

@Update(onConflict = OnConflictStrategy.REPLACE)
void update(ToDoTable toDoTable);
@Delete()
void delete(ToDoTable toDoTable);
@Query("SELECT * FROM to_Do_table")
List<ToDoTable> collectItems();

@Transaction
@Query("SELECT * FROM to_Do_table")
List<ItemsOneManyRelation> getItemsAndSubItems();



}

Sub Items RecyclerView Adapter

In this step we need to create a recyclerview adapter that hold the sub items.Moreover this adapter will be create inside the parent ToDoRecyclerAdapter class with horizontal recyclerview.

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

List<SubItems> subItemsList;

public SubItemRecyclerAdapter(List<SubItems> subItemsList) {
this.subItemsList = subItemsList;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.sub_item_row_layout,parent,false);
return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.textView.setText(subItemsList.get(position).subItemName);
}

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

class MyViewHolder extends RecyclerView.ViewHolder{

TextView textView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.subItem);
}
}
}

Update ToDo RecyclerAdapter class

public class ToDoRecyclerAdapter extends RecyclerView.Adapter<ToDoRecyclerAdapter.MyViewHolder> {
private List<ItemsOneManyRelation> toDoModelList;
private MyRoomDatabase myRoomDatabase;
Context context;
AlertDialog alertDialog;

ToDoRecyclerAdapter(List<ItemsOneManyRelation> toDoModelList, MyRoomDatabase myRoomDatabase, Context context) {
this.toDoModelList = toDoModelList;
this.myRoomDatabase=myRoomDatabase;
this.context=context;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.to_do_list_item,parent,false);
return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
final ItemsOneManyRelation toDoModel = toDoModelList.get(position);
holder.toDoItem.setText(toDoModel.toDoTable.getItem());
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
final SimpleDateFormat hFormat = new SimpleDateFormat("K:mm a",Locale.ENGLISH);
final String strDate = dateFormat.format(toDoModel.toDoTable.getDate());
holder.toDoDate.setText(strDate);
final String event_Time = hFormat.format(toDoModel.toDoTable.getTime());
holder.toDoTime.setText(event_Time);
holder.delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myRoomDatabase.myDaoInterface().delete(toDoModel.toDoTable);
toDoModelList = myRoomDatabase.myDaoInterface().getItemsAndSubItems();
notifyDataSetChanged();
}
});
holder.edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
View nView = LayoutInflater.from(context).inflate(R.layout.updateitem_layout,null);
final EditText itemName = nView.findViewById(R.id.itemName);
itemName.setText(toDoModel.toDoTable.getItem());
final TextView toDoDate = nView.findViewById(R.id.toDoDate);
toDoDate.setText(dateFormat.format(toDoModel.toDoTable.getDate()));
final TextView toDoTime = nView.findViewById(R.id.toDoTime);
toDoTime.setText(hFormat.format(toDoModel.toDoTable.getTime()));
Button updateItem = nView.findViewById(R.id.saveNewItemBtn);
Button setToDoDate = nView.findViewById(R.id.toDoDateBtn);
setToDoDate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
java.util.Calendar calendar = java.util.Calendar.getInstance();
int year = calendar.get(java.util.Calendar.YEAR);
int month = calendar.get(java.util.Calendar.MONTH);
int day = calendar.get(java.util.Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog;
datePickerDialog = new DatePickerDialog(context, new DatePickerDialog.OnDateSetListener() {

@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
final java.util.Calendar c = java.util.Calendar.getInstance(Locale.ENGLISH);
c.set(java.util.Calendar.YEAR, year);
c.set(java.util.Calendar.MONTH, month);
c.set(java.util.Calendar.DAY_OF_MONTH, dayOfMonth);
final String strDate = dateFormat.format(c.getTime());
toDoDate.setText(strDate);
toDoModel.toDoTable.setDate(c.getTime());
}
}, year, month, day);
datePickerDialog.show();

}
});

Button setToDoTime = nView.findViewById(R.id.toDoTimeBtn);
setToDoTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Calendar calendar = Calendar.getInstance();
int hours = calendar.get(Calendar.HOUR_OF_DAY);
int minuts = calendar.get(Calendar.MINUTE);
TimePickerDialog timePickerDialog = new TimePickerDialog(context, R.style.Theme_AppCompat_Dialog
, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY,hourOfDay);
c.set(Calendar.MINUTE,minute);
c.setTimeZone(TimeZone.getDefault());
SimpleDateFormat hformate = new SimpleDateFormat("K:mm a",Locale.ENGLISH);
String event_Time = hformate.format(c.getTime());
toDoTime.setText(event_Time);
toDoModel.toDoTable.setTime(c.getTime());
}
},hours,minuts,false);
timePickerDialog.show();
}
});

updateItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(toDoModel.toDoTable.getDate() == null){
Toast.makeText(context, "Select Date", Toast.LENGTH_SHORT).show();
}else if(toDoModel.toDoTable.getTime() == null){
Toast.makeText(context, "Select Time", Toast.LENGTH_SHORT).show();
}else{
String item = itemName.getText().toString();
if (TextUtils.isEmpty(item)){
Toast.makeText(context, "Insert Item Name", Toast.LENGTH_SHORT).show();

}else{
toDoModel.toDoTable.setItem(item);
myRoomDatabase.myDaoInterface().update(toDoModel.toDoTable);
myRoomDatabase.myDaoInterface().collectItems();
notifyDataSetChanged();
alertDialog.dismiss();

}
}
}
});

builder.setView(nView);
alertDialog = builder.create();
alertDialog.show();

}
});
holder.complete.setChecked(toDoModel.toDoTable.isCompleted());
if (toDoModel.toDoTable.isCompleted()){
holder.toDoItem.setPaintFlags(holder.toDoItem.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}else{
holder.toDoItem.setPaintFlags(0);
}

holder.setItemClickListener(new MyOnClickListener() {
@Override
public void onClickListener(View view, int mPosition) {
CheckBox checkBox = (CheckBox)view;
if (checkBox.isChecked()){
toDoModel.toDoTable.setCompleted(true);
}else{
toDoModel.toDoTable.setCompleted(false);
}
myRoomDatabase.myDaoInterface().update(toDoModel.toDoTable);
myRoomDatabase.myDaoInterface().collectItems();
notifyDataSetChanged();
}
});
holder.recyclerView.setHasFixedSize(true);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL,false));
final SubItemRecyclerAdapter subItemRecyclerAdapter = new SubItemRecyclerAdapter(myRoomDatabase.myDaoInterface().getItemsAndSubItems().get(position).subItems);
holder.recyclerView.setAdapter(subItemRecyclerAdapter);
subItemRecyclerAdapter.notifyDataSetChanged();
holder.addSubItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(true);
View nView = LayoutInflater.from(context).inflate(R.layout.insert_subitem_layout,null);
final EditText editText = nView.findViewById(R.id.subItemEditTxt);
Button button = nView.findViewById(R.id.addSubItem);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SubItems subItems = new SubItems();
subItems.setSubItemName(editText.getText().toString());
subItems.setId(toDoModel.toDoTable.getId());
myRoomDatabase.myDaoInterface().insertSubItem(subItems);
toDoModelList = myRoomDatabase.myDaoInterface().getItemsAndSubItems();
notifyDataSetChanged();
alertDialog.dismiss();

}
});

builder.setView(nView);
alertDialog = builder.create();
alertDialog.show();
}
});
}




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

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView toDoItem,toDoDate,toDoTime;
Button edit,delete,addSubItem;
CheckBox complete;
RecyclerView recyclerView;
private MyOnClickListener myOnClickListener;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
toDoItem = itemView.findViewById(R.id.toDoItem);
toDoDate = itemView.findViewById(R.id.toDoDate);
toDoTime = itemView.findViewById(R.id.toDoTime);
edit = itemView.findViewById(R.id.edit);
delete = itemView.findViewById(R.id.delete);
complete = itemView.findViewById(R.id.complete);
addSubItem = itemView.findViewById(R.id.subItem);
recyclerView = itemView.findViewById(R.id.subItemRV);
complete.setOnClickListener(this);
}

void setItemClickListener(MyOnClickListener myOnClickListener){
this.myOnClickListener = myOnClickListener;
}
@Override
public void onClick(View v) {
this.myOnClickListener.onClickListener(v,getLayoutPosition());
}
}
}

Update Main Activity Java class

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
    private Button addNewItem;
    private RecyclerView recyclerView;
    public List<ItemsOneManyRelation> toDoModelList = new ArrayList<>();
    private MyRoomDatabase myRoomDatabase;
    private SwipeRefreshLayout swipeRefreshLayout;
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolBar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle("To Do List");

        addNewItem = findViewById(R.id.addNewItemActivityBtn);
        addNewItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,NewItemActivityActivity.class));
                finish();
            }
        });
        swipeRefreshLayout = findViewById(R.id.swipe);
        swipeRefreshLayout.setOnRefreshListener(this);

        myRoomDatabase = MyRoomDatabase.getInstance(getApplicationContext());
        recyclerView = findViewById(R.id.toDoRecyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        collectItems();





    }

    private void collectItems(){
        swipeRefreshLayout.setRefreshing(true);
        toDoModelList = myRoomDatabase.myDaoInterface().getItemsAndSubItems();
        Log.d("TAG", "collectItems: "+toDoModelList.size());

        RecyclerView.Adapter adapter = new ToDoRecyclerAdapter(toDoModelList, myRoomDatabase, this);
        recyclerView.setAdapter(adapter);
        adapter.notifyDataSetChanged();
        swipeRefreshLayout.setRefreshing(false);
    }

    @Override
    public void onRefresh() {
collectItems();

    }

Finally, run your app to add items and their sub items. If you encountered errors please comment.

Thank You

1 thought on “Room Database Entities Relationships”

  1. would be nice if you could explain how to edit the child items, thanks for the article came in handy for my project now stock at the editing of the sub items.

Leave a Comment

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