Android Realm Database Tutorial

Hi Guys,

Is there an alternative to SQlite database? Sure there is one… Realm Database.

Realm Database can be used for offline syncing much like SQlite but in an much more efficient way.

You can take a look at this link for more details.

Download LinkAndroid Realm Database Tutorial

Demo Video

build.gradle


dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
compile 'io.realm:realm-android:0.84.1'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.android.support:design:25.2.0'
compile 'com.android.support:cardview-v7:25.2.0'
compile 'com.squareup.picasso:picasso:2.5.2'
testCompile 'junit:junit:4.12'
}

This is how the build.gradle file looks like in my case.

Now First the Realm configuration file is created and named as MainApplication.java.

MainApplication.java


public class MainApplication extends Application {

@Override
public void onCreate() {
super.onCreate();
RealmConfiguration config=new RealmConfiguration.Builder(this)
.schemaVersion(4)
.deleteRealmIfMigrationNeeded()
.build();
Realm.setDefaultConfiguration(config);
}
}

Basically this file acts as a configuration file. Then this MainApplication file must be
set in the manifest file.

AndroidManifest.xml


<application 
android:name=".MainApplication" 
android:allowBackup="true" 
android:icon="@drawable/cozycodes" 
android:label="@string/app_name" 
android:supportsRtl="true" 
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

Next is the Sample java class where all the data models are created. This can be done by extending
the RealmObject base class.

Here Primary key annotation can be set and in this case String name is used which
I would not recommend it is always good to use integer as Primary Key.
Sample.java

public class Sample extends RealmObject{

 @PrimaryKey
 private String name;
 private String address;
 private String age;
 private String image;

 public String getName(){
 return name;
 }

 public void setName(String name){
 this.name = name;
 }

 public String getAddress(){
 return address;
 }

 public void setAddress(String address){
 this.address = address;
 }

 public String getAge(){
 return age;
 }

 public void setAge(String age){
 this.age = age;
 }

 public String getImage(){
 return image;
 }

 public void setImage(String image){
 this.image = image;
 }
}

RealmConnect class is a helper class which has all the methods for the Realm Database methods.
RealmConnect is a Singleton Class. To know much more about Singleton class visit this link.

RealmConnect.java

public class RealmConnect {

    Realm realm;
    RealmResults<Sample> sample;
    Boolean add=null;
    private static RealmConnect instance;

    public RealmConnect(Application application) {
        realm = Realm.getDefaultInstance();
    }

    public RealmConnect(Realm realm) {
        this.realm = realm;
    }


    public Boolean add(final Sample sample)
    {
        if(sample == null)
        {
            add = false;
        }else
        {
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {

                    try
                    {
                        Sample val = realm.copyToRealm(sample);
                        add = true;

                    }catch (RealmException e)
                    {
                        e.printStackTrace();
                        add = false;
                    }
                }
            });
        }

        return add;
    }


    public void selectDB()
    {
        sample = realm.where(Sample.class).findAll();
    }


    public ArrayList<Sample> dataReload()
    {
        ArrayList<Sample> latest=new ArrayList<>();
        for(Sample s : sample)
        {
            latest.add(s);
        }

        return latest;
    }



    public static RealmConnect getInstance() {

        return instance;
    }

    public Realm getRealm() {

        return realm;
    }

    public static RealmConnect with(Activity activity) {

        if (instance == null) {
            instance = new RealmConnect(activity.getApplication());
        }
        return instance;
    }


}

 

Then we have a Recyclerview for the Main Activity named as SampleAdapter.
SampleAdapter has the action functions such long press for delete and tap for editind the Realm database items.

SampleAdapter.java

public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.MyHolder> {
 List<Sample> wishes = new ArrayList<>();
 Sample val;
 private Realm realm;
 Context mContext;
 ArrayList<Sample> sample;
 private LayoutInflater inflater;

 public SampleAdapter(Context context, ArrayList<Sample> sample) {
 this.mContext = context;
 this.sample = sample;
 }

 @Override
 public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 View v= LayoutInflater.from(mContext).inflate(R.layout.listing,parent,false);
 return new MyHolder(v);
 }

 @Override
 public void onBindViewHolder(final MyHolder holder, final int position) {

 realm = RealmConnect.getInstance().getRealm();
 val = sample.get(position);

 holder.in_name.setText(val.getName());
 holder.in_address.setText(val.getAddress());
 holder.in_age.setText(val.getAge());

 String imageUrl = val.getImage().replace("https","http");

 LoadImage.downloadImage(mContext,imageUrl,holder.profile_img);

 // Long Press to delete item
 holder.cardview.setOnLongClickListener(new View.OnLongClickListener() {
 @Override
 public boolean onLongClick(View v) {
 AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
 builder.setTitle("Delete User");
 builder.setMessage("Are you sure?");
 builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 RealmResults<Sample> results = realm.where(Sample.class).findAll();

 realm.beginTransaction();
 results.remove(position);
 realm.commitTransaction();

 }
 });
 builder.setNegativeButton("No", null);
 builder.show();

 return false;
 }
 });

 // Click to Edit item values
 holder.cardview.setOnClickListener(new View.OnClickListener() {

 @Override
 public void onClick(View v) {

 inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 View content = inflater.inflate(R.layout.edit_listing, null);
 final EditText editTitle = (EditText) content.findViewById(R.id.Et_name);
 final EditText editAuthor = (EditText) content.findViewById(R.id.Et_address);
 final EditText editThumbnail = (EditText) content.findViewById(R.id.Et_age);
 final EditText editUrl = (EditText) content.findViewById(R.id.Et_url);

 editTitle.setText(sample.get(position).getName());
 editAuthor.setText(sample.get(position).getAddress());
 editThumbnail.setText(sample.get(position).getAge());
 editUrl.setText(sample.get(position).getImage());

// Toast.makeText(mContext, sample.get(position).getName() , Toast.LENGTH_SHORT).show();
 AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
 builder.setView(content)
 .setTitle("Edit User")
 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {

 RealmResults<Sample> results = realm.where(Sample.class).findAll();

 realm.beginTransaction();
 results.get(position).setAddress(editAuthor.getText().toString());
 results.get(position).setName(editTitle.getText().toString());
 results.get(position).setAge(editThumbnail.getText().toString());
 results.get(position).setImage(editUrl.getText().toString());

 realm.commitTransaction();

// notifyDataSetChanged();
 dialog.dismiss();
 }
 })
 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

 @Override
 public void onClick(DialogInterface dialog, int which) {
 dialog.dismiss();
 }
 });
 AlertDialog dialog = builder.create();
 dialog.show();
 }
 });

 }

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


 public class MyHolder extends RecyclerView.ViewHolder {

 TextView in_name,in_address,in_age;
 ImageView profile_img;
 CardView cardview;

 public MyHolder(View itemView) {
 super(itemView);

 in_name= (TextView) itemView.findViewById(R.id.in_name);
 in_address= (TextView) itemView.findViewById(R.id.in_address);
 in_age= (TextView) itemView.findViewById(R.id.in_age);
 profile_img= (ImageView) itemView.findViewById(R.id.profile_img);
 cardview = (CardView) itemView.findViewById(R.id.cardview);
 }
 }

}

 

Finally the MainActivity,

MainActivity.java

public class MainActivity extends AppCompatActivity {

 Realm realm;
 RealmChangeListener realmChangeListener;
 SampleAdapter adapter;
 RecyclerView sample_recyclerview;
 EditText Et_name,Et_address,Et_age,Et_url;
 String name, address, age, image_url;

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

 sample_recyclerview= (RecyclerView) findViewById(R.id.sample_recycler);
 sample_recyclerview.setLayoutManager(new LinearLayoutManager(this));

 this.realm = RealmConnect.with(this).getRealm();

 final RealmConnect connect = new RealmConnect(realm);
 connect.selectDB();

 adapter=new SampleAdapter(this,connect.dataReload());
 sample_recyclerview.setAdapter(adapter);

 realmChangeListener=new RealmChangeListener() {
 @Override
 public void onChange() {

 adapter=new SampleAdapter(MainActivity.this,connect.dataReload());
 sample_recyclerview.setAdapter(adapter);
 }
 };

 realm.addChangeListener(realmChangeListener);

 FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
 fab.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 addNewUser();
 }
 });
 }


 @Override
 protected void onDestroy() {
 super.onDestroy();
 // data changes are informed on the view
 realm.removeChangeListener(realmChangeListener);
 realm.close();
 }

 //Function to add new user
 private void addNewUser()
 {
 Dialog alert = new Dialog(this);
 alert.setTitle("New User");
 alert.setContentView(R.layout.input_dialog);

 Et_name = (EditText) alert.findViewById(R.id.Et_name);
 Et_address = (EditText) alert.findViewById(R.id.Et_address);
 Et_age = (EditText) alert.findViewById(R.id.Et_age);
 Et_url = (EditText) alert.findViewById(R.id.Et_url);
 Button addBtn = (Button) alert.findViewById(R.id.addBtn);


 addBtn.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {

 name = Et_name.getText().toString();
 address = Et_address.getText().toString();
 age = Et_age.getText().toString();
 image_url = Et_url.getText().toString();

 if(name != null && name.length()>0)
 {

 Sample sample = new Sample();
 sample.setName(name);
 sample.setAddress(address);
 sample.setAge(age);
 sample.setImage(image_url);

 RealmConnect connect = new RealmConnect(realm);

 if(connect.add(sample))
 {
 Et_name.setText("");
 Et_address.setText("");
 Et_age.setText("");
 Et_url.setText("");

 }else {
 Toast.makeText(MainActivity.this, "Invalid", Toast.LENGTH_SHORT).show();
 }

 }else {
 Toast.makeText(MainActivity.this, "Field Cannot be Empty", Toast.LENGTH_SHORT).show();
 }

 }
 });

 alert.show();

 }
}

The MainActivity class has the major items declared in it such as RecyclerView, Adpater changes and
RealmController instantiation. There is a listener placed in the MainActivity which informs the adapter about any
data changes and no separate function such as notifyDataSetChanged() needs to be called.

sample_recyclerview= (RecyclerView) findViewById(R.id.sample_recycler);
 sample_recyclerview.setLayoutManager(new LinearLayoutManager(this));

 this.realm = RealmConnect.with(this).getRealm();

 final RealmConnect connect = new RealmConnect(realm);
 connect.selectDB();

 adapter=new SampleAdapter(this,connect.dataReload());
 sample_recyclerview.setAdapter(adapter);

 realmChangeListener=new RealmChangeListener() {
 @Override
 public void onChange() {

 adapter=new SampleAdapter(MainActivity.this,connect.dataReload());
 sample_recyclerview.setAdapter(adapter);
 }
 };

 realm.addChangeListener(realmChangeListener);

Realm Database is a much more efficient way for syncing data to offline.

 

Download LinkAndroid Realm Database Tutorial

Leave a Reply

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