Abdullah Al Imran Abdullah Al Imran - 3 months ago 14
Java Question

Is this the correct approach of using Realm in Android?

I've decided to use Realm to one of my Android app. That's why I'm just trying to make a simple app with Realm for R&D purpose. But I'm confused if it is the correct way to use Realm. My project is working and showing data correctly. Here are my codes-

I created a java class

RealmDB.java
:

package com.github.abdalimran.realmandroid;

import android.app.Application;
import android.content.Context;

import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;

public class RealmDB extends Application{

private Realm myRealm;

public RealmDB(Context context) {
myRealm = Realm.getInstance(new RealmConfiguration.Builder(context)
.name("myOtherRealm.realm")
.build());
}

public void addData(PersonDetailsModel p) {
myRealm.beginTransaction();
PersonDetailsModel person = myRealm.createObject(PersonDetailsModel.class);
person.setName(p.getName());
person.setAge(p.getAge());
person.setEmail(p.getEmail());
person.setAddress(p.getAddress());
myRealm.commitTransaction();
}

public RealmResults getAllData() {
RealmResults<PersonDetailsModel> query = myRealm.where(PersonDetailsModel.class).findAll();
return query;
}

public void closeRealm() {
myRealm.close();
}
}


Now I am creating an instance of this class and perform operations using the methods.

Here is my Realm Object class
PersonDetailsModel.java
:

package com.github.abdalimran.realmandroid;

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

public class PersonDetailsModel extends RealmObject
{
@PrimaryKey
private String id;
private String name;
private String email;
private String address;
private int age;

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "ID: "+getId()+"\n"+
"Name: "+getName()+"\n"+
"Age: "+getAge()+"\n"+
"Email: "+getEmail()+"\n"+
"Address: "+getAddress()+"\n";
}
}


This is the
MainActivity.java
where I'm instantiating the RealmDB class and performing operations:

package com.github.abdalimran.realmandroid;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

private ListView lvPersonNameList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvPersonNameList= (ListView) findViewById(R.id.lvPersonNameList);

RealmDB rdb=new RealmDB(this);

Log.i("list",""+rdb.getAllData());

if(rdb.getAllData()==null){
Toast.makeText(MainActivity.this, "No data found. Add person.", Toast.LENGTH_SHORT).show();
}
else {
ArrayAdapter<PersonDetailsModel> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1,
android.R.id.text1,
rdb.getAllData());
lvPersonNameList.setAdapter(adapter);
}
}


public void AddPerson(View view) {
Intent intent=new Intent(this,AddPersonActivity.class);
startActivity(intent);
}
}


Here is my
AddPersonActivity.java
class-

package com.github.abdalimran.realmandroid;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.text.SimpleDateFormat;
import java.util.Date;

public class AddPersonActivity extends AppCompatActivity {

private EditText name;
private EditText age;
private EditText email;
private EditText address;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_person);

name= (EditText) findViewById(R.id.name);
age= (EditText) findViewById(R.id.age);
email= (EditText) findViewById(R.id.email);
address= (EditText) findViewById(R.id.address);
}

public void AddPerson(View view) {

Date dNow = new Date();
SimpleDateFormat ft = new SimpleDateFormat("yyMMddhhmmssMs");
String uniqueid = ft.format(dNow);

Log.i("uniqueid",uniqueid);

String sname=name.getText().toString();
String sage=age.getText().toString();
String semail=email.getText().toString();
String saddress=address.getText().toString();

PersonDetailsModel person=new PersonDetailsModel();
person.setId(uniqueid);
person.setName(sname);
person.setAge(Integer.parseInt(sage));
person.setEmail(semail);
person.setAddress(saddress);

RealmDB rdb=new RealmDB(getApplicationContext());
rdb.addData(person);
rdb.closeRealm();
}
}


Is this a correct approach to implement Realm into Android project?

Mostly I'm confused with the following code:

public void addData(PersonDetailsModel p) {
myRealm.beginTransaction();
PersonDetailsModel person = myRealm.createObject(PersonDetailsModel.class);
person.setName(p.getName());
person.setAge(p.getAge());
person.setEmail(p.getEmail());
person.setAddress(p.getAddress());
myRealm.commitTransaction();
}


Here I have a parameter
PersonDetailsModel p
. But I'm creating a realm object using
myRealm.createObject(PersonDetailsModel.class);
and then getting the data from
p
and setting it to
person
. Isn't there a way to directly set the parameter
p
into
createObject()
?

Answer
public class RealmDB extends Application {
    public RealmDB(Context context) {

Based on these two lines, I can tell you quite clearly that it isn't.

And with that,

0.a) you shouldn't make "Application" instances by hand, "Application" is created by Android

0.b) Your public RealmResults getAllData() { should be public RealmResults<PersonDetailsModel> getAllData() {

1.) you are not using RealmBaseAdapter and you should, so you don't handle updates in the Realm either with RealmBaseAdapter nor with RealmChangeListener

2.) you are not using executeTransactionAsync() on the UI thread and you should (in fact, you should use executeTransaction() for synchronous transactions, and you shouldn't execute synchronous writes on the UI thread)

3.) your Realm instance created in MainActivity is never closed

4.) you should retain a field variable to your RealmResults to prevent it from getting GC'd (although ArrayAdapter might also latch onto it, so you won't run into the problem that comes from not retaining a field variable to the results)