Repository
https://github.com/realm/realm-java
What Will I Learn?
- You will learn Relationships in Realm
- Many To Many Relationship
- Inverse Relationship
Requirements
- An Integrated Development Environment(IDE) for building Android Application(e.g Android Studio, IntelliJ)
- Android Device/Virtual Device.
- Little Experience in working with Realm Java.
- Java Programming Experience.
- Of course, willingness to learn
Resources
- Retrofit Website. https://realm.io/
- Retrofit Github. - https://github.com/realm
- Retrofit License - Apache License
Difficulty
- Intermediate
Tutorial Duration - 25 - 30Mins
Tutorial Content
In Today's tutorial, we are going to continue learning about relationships in realm database. We are going to basically be looking at two levels of relationships - Many to Many
and Inverse
Relationships.
The part 1 of this tutorial can be found - here
How Can Relationships be achieved in Realm Database?
Realm lets you define relationships between objects by linking them together, a class becomes a RealmObject is that class extends from the RealmObject
class. i.e - public class MyClass extends RealmObject
.
In order to explain the relationships, we are going to improve our android application in which the landing page will now have two new buttons, each representing the two relationships.
Next, we will be creating two new fragments which will be representing the relationships and once a user clicks any button, the appropriate fragment will be called.
We would be using the scenario of a Teacher and a Group in which a Teacher in a Many-to-Many
relationship will be Many teacher to Many group
and in an Inverse Relationship
we will be getting the list of Teachers that are associated with a Group
.
Outline
- Add Two new Buttons in our activity_main.xml file.
- Create Two New Fragments.
- Edit Our MainActivity.java class file.
- Create the Necessary Model Classes.
- Show Relationships in Fragments.
Add Two new Buttons
In our part one of this tutorial, our application only contained two buttons for the one - to - one
and the one to many
relationship, but in this second part of this tutorial, we will be adding two new buttons to our activity_main.xml file -
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/mainLayout"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
//One to One and One to Many Buttons above
<Button
android:id="@+id/manyToMany"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Many to Many Relationship" />
<Button
android:id="@+id/inverseRelationship"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Inverse Relationship" />
</LinearLayout>
</RelativeLayout>
In the layout code above, it is important to note that the LinearLayout
is displayed in the center of the parent layout which is the RelativeLayout
by this line - android:layout_centerInParent="true"
and also, all buttons apart from the first button has a margin to their top of 20dp - android:layout_marginTop="20dp"
.
We have now added two new buttons with the id's - manyToMany
,inverseRelationship
and with the text - Many to Many Relationship
and Inverse Relationship
respectively.
Create Two Fragments
We will be creating two new fragments which we will be using to explain the two relationships we will be looking at today.
To create a new blank fragment, right click on your java folder => New => Fragment => Blank Fragment.
Next, Name your fragment - ManyToMany
and then do not forget to uncheck the - Include fragment factory methods?
and include interface callbacks
checkboxes
Repeat the process for the remaining fragment and make sure to give it a unique name as two fragments can't have the same name.
You can name the remaining fragment - InverseRelatonship
inorder to follow along with the tutorial.
Add Fragment Transactions in MainActivity.java class
Next, in our mainActivity.java we will be using butterknife to inject the onClick methods for our two new buttons and then we will be using FragmentTransaction to call the aappropriate fragment based on the button that was clicked.
To inject the onClick methods of the new buttons using butterknife, place your cursor on the layout name on the setContentView()
method and then on windows - alt + ins => Generate ButterKnife Injection and then select the checkboxes shown in the image below:
Injected Code
The MainActivity.java class file should now look like this
@OnClick({R.id.oneToOne, R.id.oneToMany, R.id.manyToMany, R.id.inverseRelationship})
public void onViewClicked(View view) {
switch (view.getId()) {
//Previous cases
case R.id.manyToMany:
showManyToManyFragment();
break;
case R.id.inverseRelationship:
showInverseFragment();
break;
}
}
Note: The showManyToManyFragment()
,showInverseFragment()
wasn't added by butterknife.
showManyToManyFragment()
private void showManyToManyFragment() {
ManyToMany manyToMany = new ManyToMany();
showFragment(manyToMany);
}
In this method, we create a ManyToMany Fragment object and then pass it as an argument to the showFragment()
method.
The same step is taken in all the other method - showInverseFragment()
private void showInverseFragment() {
InverseRelationship inverse = new InverseRelationship();
showFragment(inverse);
}
showFragment()
private void showFragment(Fragment fragment) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.mainLayout,fragment).addToBackStack(fragment.getTag());
ft.commit();
}
Firstly, we get a FragmentManager
object and set it to the getFragmentManger()
and then we get a FragmentTransaction
object - ft
and begin a transaction with it on the FragmentManager
object - fragmentManager
.
We then call the replace method on the FragmentTransaction
object passing the id of the view we want replaced and the the fragment to replace it as the arguments.
Note: The mainLayout
id is the id of the RelativeLayout
which is the root layout for our activity_main.xml
file.
We then add the fragment to backStack using the addToBackStack()
method and getting the tag from the fragment as the argument and finally we call commit()
on the transaction.
Create the Necessary Model Classes
Many To Many Relationship
To set up a many-to-many relationship, one of the properties of a model will be a type of a RealmObject subclasses:
We will be using our TeacherMany
class and our Group
class which extends the RealmObject
class to show this relationship
TeacherMany.java
public class TeacherMany extends RealmObject {
public String name;
public String course;
public RealmList<Group> groups;
}
The group property is of the type Group
which is a RealmObject.
Group.java
public class Group extends RealmObject {
public String name;
public int number_of_students;
}
ManyToMany.java
Firstly, we declear a realm object - private Realm realm;
.
Inside our onCreate()
method just before the return view
line we insert the following codes.
To establish the ManyToMany
relationship, we create two TeacherMany
realm objects and two Group
realm objects and then create a many to many relationship between them by by setting the two groups to each of the TeacherMany
realm objects.
...
Realm.init(getActivity());
Realm.deleteRealm(Realm.getDefaultConfiguration());
realm = Realm.getDefaultInstance();
realm.beginTransaction();
TeacherMany teacher = realm.createObject(TeacherMany.class);
teacher.name = "Edet Ebenezer";
teacher.course = "Microbiolgy";
TeacherMany teacher2 = realm.createObject(TeacherMany.class);
teacher2.name = "Joseph Ikenna";
teacher2.course = "Computer Science";
Group blue_group = realm.createObject(Group.class);
blue_group.name = "Blue Group";
blue_group.number_of_students = 25;
Group purple_group = realm.createObject(Group.class);
purple_group.name = "Purple Group";
purple_group.number_of_students = 32;
teacher.groups.add(blue_group);
teacher.groups.add(purple_group);
teacher2.groups.add(blue_group);
teacher2.groups.add(purple_group);
realm.commitTransaction();
String toDisplay = teacher.name + " is teaching " + teacher.groups.size() + " Groups Namely - " + teacher.groups.get(0).name + " with " + teacher.groups.get(0).number_of_students + " students"
+ " and " + teacher.groups.get(1).name + " with " + teacher.groups.get(1).number_of_students;
String toDisplay2 = teacher2.name + " is teaching " + teacher2.groups.size() + " Groups Namely - " + teacher2.groups.get(0).name + " with " + teacher2.groups.get(0).number_of_students + " students"
+ " and " + teacher2.groups.get(1).name + " with " + teacher2.groups.get(1).number_of_students;
relationshipManyMany.setText(toDisplay);
relationshipManyMany2.setText(toDisplay2);
...
Code Explanation
First, we initialize the Realm in our fragment, we then start with a clean slate by calling the deleteRealm()
method on the defaultConfiguration file.
Next, we begin a realm transaction - realm.beginTransaction()
and then we create two Realm object's of the TeacherMany
class, we set the name and the course of the first (teacher) - teacher.name = "Edet Ebenezer"
,eben.course = "Microbioogy"
respectively and the second TeacherMany
realm object (teacher2) name and course - teacher2.name = "Joseph Ikenna"
,teacher2.course = "Computer Science"
respectively.
We then create a two Group
object's - blue_group
and set its name to "Blue Group"
and the number of students to 25 and purple_group
and set its name to "Purple Group"
and the its number of student property to 32.
We then establish a many-to-many relationship between the two TeacherMany
and the Group
realm objects by setting two groups to each of the teacher
and teacher2
realm objects.
teacher.groups.add(blue_group);
teacher.groups.add(purple_group);
teacher2.groups.add(blue_group);
teacher2.groups.add(purple_group);
Lastly, we concatenate the name of each teachers, the number of groups they are assigned to, the name of the groups and also the number of students in each group in two String variables - toDisplay
,toDisplay2
.
This is then set as the text of two TextViews in our ManyToMany
Fragment layout file - many_to_many_fragment.xml
with the id's - relationshipManyMany
and relationshipManyMany2
which was injected using Buterknife
.
Explanation
- We get the teacher's name by
teacher.name
and the course byteacher.course
- We get the size of the groups the teacher is assigned to by -
teacher.groups.size()
and the name of the group the teacher is assigned to by -teacher.groups.get(0).name
for the first group andteacher.groups.get(1).name
for the second group and then the number of students byeben.groups.get(0).number_of_students
for the first group andeben.groups.get(1).number_of_students
for the second group.
NB: You have to edit the layout of your ManyToMany
Fragment and input the following which just inserts a two TextView
's' to the layout.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#FFF"
android:layout_height="match_parent"
tools:context=".ManyToMany">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relationshipManyMany"
android:text="@string/hello_blank_fragment"
android:layout_centerInParent="true"
android:padding="10dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relationshipManyMany2"
android:text="@string/hello_blank_fragment"
android:layout_centerInParent="true"
android:layout_marginTop="20dp"
android:layout_below="@+id/relationshipManyMany"
android:padding="10dp"
/>
</RelativeLayout>
Inverse Relationship
In our previous relationships, it is easy for us to follow the link from Teacher
to Group
but there is no way to go from Group
to Teacher
object which can be resolved by giving the Group a @LinkingObjects
annotation.
So for the Inverse Relationship, we create a new java class file - InverseGroup
and extend from the RealmObject
class -
public class InverseGroup extends RealmObject {
public String name;
public int number_of_students;
@LinkingObjects("groups")
public final RealmResults<TeacherInverse> teachers = null;
}
We’ve given InverseGroup
a teachers field, and specified that it should contain all TeacherMany
objects that have this InverseGroup
object in their teachers
field.
The annotated field must be declared final and must be of type RealmResults<> where it must hava a type or class of the opposite end of the relationship, one should also note that inverse relationships can result in 0 or 1 or even more objects.
We will also be creating a new java class - TeacherInverse
public class TeacherInverse extends RealmObject {
public String name;
public String course;
public RealmList<InverseGroup> groups;
}
We changed the type of the RealmList
to InverseGroup
just created above.
InverseRelationship.java
Firstly, we declear a realm object - private Realm realm;
.
Inside our onCreate()
method just before the return view
line we insert the following codes.
...
Realm.init(getActivity());
Realm.deleteRealm(Realm.getDefaultConfiguration());
realm = Realm.getDefaultInstance();
realm.beginTransaction();
TeacherInverse teacher = realm.createObject(TeacherInverse.class);
teacher.name = "Smith Williams";
teacher.course = "French";
TeacherInverse teacher2 = realm.createObject(TeacherInverse.class);
teacher2.name = "Frank Houston";
teacher2.course = "Agriculture";
InverseGroup green_group = realm.createObject(InverseGroup.class);
green_group.name = "Green Group";
green_group.number_of_students = 8;
InverseGroup white_group = realm.createObject(InverseGroup.class);
white_group.name = "White Group";
white_group.number_of_students = 20;
teacher.groups.add(green_group);
teacher.groups.add(white_group);
teacher2.groups.add(green_group);
teacher2.groups.add(white_group);
realm.commitTransaction();
String stringTeacher1 = green_group.name+" has "+green_group.teachers.size()+" teachers - "+ green_group.teachers.get(0).name+" teaching them "+green_group.teachers.get(0).course
+" and "+green_group.teachers.get(1).name+" teaching them "+green_group.teachers.get(1).course;
String stringTeacher2 = white_group.name+" has "+white_group.teachers.size()+" teachers - "+ white_group.teachers.get(0).name+" teaching them "+white_group.teachers.get(0).course
+" and "+white_group.teachers.get(1).name+" teaching them "+white_group.teachers.get(1).course;
relationshipInverse.setText(stringTeacher1);
relationshipInverse2.setText(stringTeacher2);
...
Explanation
- We get the name of the group by -
green_group.name
, the number of teachers assgined to the group by -green_group.teachers.size()
and then the name of the two teachers of a group bygreen_group.teachers.get(0).name
andgreen_group.teachers.get(1).name
and their courses bygreen_group.teachers.get(0).course
andgreen_group.teachers.get(1).course
- We get the same details as explained above for the second group -
white_group
.
We then display this details in two TextViews
that exist in the layout file of our InverseRelationship
Fragment - inverse_relationship_fragment.xml
with the id's - relationshipInverse
, relationshipInverse2
which was injected using Butterknife
NB: You have to edit the layout of your InverseRelationship
Fragment and input the following which just inserts two TextView
's' to the layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="#FFF"
android:layout_height="match_parent"
tools:context=".InverseRelationship">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relationshipInverse"
android:text="@string/hello_blank_fragment"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:padding="10dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relationshipInverse2"
android:text="@string/hello_blank_fragment"
android:gravity="center_horizontal"
android:padding="10dp"
android:layout_below="@+id/relationshipInverse"
android:layout_marginTop="20dp"
/>
</RelativeLayout>
NB: We have to close the realm database on the onDestroy
method of our fragment for both the ManyToMany
and InverseRelationship
Fragments.
@Override
public void onDestroyView() {
super.onDestroyView();
realm.close();
}
Application Execution
Curriculum
Complete Source code:
https://github.com/generalkolo/Realm-JSON/tree/master/Realm%20Relationships
Thank you for the contribution! Try to utilize markdowns a bit more for increased readability.
Your contribution has been evaluated according to Utopian rules and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post,Click here
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Thanks @deathwing for moderating my post.
Markdowns will be utilized more in subsequent contributions.
Hey @edetebenezer
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Contributing on Utopian
Learn how to contribute on our website or by watching this tutorial on Youtube.
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!