We all know the good old SQLite when times are asking for an internal storage. But times are changing and here it comes Realm which is on a great way to replace SQLite.

Note: The Realm version for this demo is 0.82.1, as a more stable version. The latest version at the moment is 0.90.0. For further info check https://realm.io/docs/java/latest/

android working with realm database

What is Realm?

Realm is a mobile database and a replacement for SQLite. Although is an OO database it has some differences with other databases. Realm is not using SQLite as it’s engine. Instead it has own C++ core and aims to provide a mobile-first alternative to SQLite. Realm store data in a universal, table-based format by a C++ core. This is what allows Realm to allow data access from multiple languages as well as a range of ad hoc queries.

Below are the advantages of Realm over SQLite:
> faster than SQLite (up to 10x speed up over raw SQLite for normal operations)
> easy to use
> object conversion handled for you
> convenient for creating and storing data on the fly
> very responsive team

Also there are some disadvantages which might be taken into consideration:
> no importing
> still under active development
> not a lot of content online
> can’t access objects across threads

Realm at the moment is missing the following features:
> null support
> auto incrementing id’s
> Map support
> easy migrations
> notifications on specific data changed
> compound primary keys

android-realm-database-tutorial

Building E-Book App

Note: If you receive any problems during running the project after changes have been done to the realm, you might need to uninstall the app and run it again.

android-studio-creating-realm-database-app

1. Create a new project in Android Studio from File ⇒ New Project. When it prompts you to select the default activity, select Blank Activity and proceed.

2. Open build.gradle and add Realm, Glide, CardView and RecyclerView dependencies. RecyclerView and CardView are used to show the realm data and Glide is for showing images.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:support-v4:23.3.0'
    compile 'com.android.support:design:23.3.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'

    // Realm
    compile 'io.realm:realm-android:0.82.1'
    // RecyclerView
    compile 'com.android.support:recyclerview-v7:23.3.0'
    // CardView
    compile 'com.android.support:cardview-v7:23.3.0'
}

3. Open dimens.xml located under res ⇒ values and add the following dimensions.

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="margin_normal">8dp</dimen>
    <dimen name="margin_large">16dp</dimen>
    <dimen name="text_size_large">16sp</dimen>
    <dimen name="margin_small">0dp</dimen>
    <dimen name="text_size_normal">13sp</dimen>
    <dimen name="imge_book_detail">80dp</dimen>
</resources>

4. Add the below styles to your styles.xml located under res ⇒ values. Here we define styles for the CardView.

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.Card.Margins" parent="CardView">
        <item name="android:layout_marginTop">@dimen/margin_normal</item>
        <item name="android:layout_marginBottom">@dimen/margin_normal</item>
        <item name="android:layout_marginLeft">@dimen/margin_large</item>
        <item name="android:layout_marginRight">@dimen/margin_large</item>
        <item name="android:clickable">true</item>
        <item name="android:focusable">true</item>
        <item name="android:foreground">?android:attr/selectableItemBackground</item>
        <item name="cardCornerRadius">@dimen/margin_small</item>
        <item name="cardPreventCornerOverlap">false</item>
        <item name="cardBackgroundColor">@android:color/white</item>
    </style>

</resources>

5. Create four packages named app, activity, adapters, model and realm and place your MainActivity.java under activity package. These packages helps in keeping your project organized.

6. Realms are the equivalent of a database: they contain different kinds of objects, and map to one file on disk. The most basic setup for realm is by calling:

// Obtain realm instance
Realm realm = Realm.getInstance(this);

Calling Realm.getInstance(context) makes it easy to get started with Realm. For more fine-grained control, it is possible to create a RealmConfiguration object that controls all aspects of how a Realm is created.

Create a class named MyApplication.java under app package. Here we setup the realm configuration.

package app.androidhive.info.realm.app;

import android.app.Application;

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

public class MyApplication extends Application {

    @Override
    public void onCreate() {

        super.onCreate();
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
                .name(Realm.DEFAULT_REALM_NAME)
                .schemaVersion(0)
                .deleteRealmIfMigrationNeeded()
                .build();
        Realm.setDefaultConfiguration(realmConfiguration);

    }
}

The RealmConfiguration can be saved as a default configuration. Setting a default configuration in your custom Application class, will ensure that it is available in the rest of your code.

It is also possible to have multiple RealmConfigurations. In this way you can control the version, schema and location of each Realm independently.

/*
RealmConfiguration myConfig = new RealmConfiguration.Builder(context)
        .name("myrealm.realm").
.schemaVersion(2)
        .setModules(new MyCustomSchema())
        .build();

RealmConfiguration otherConfig = new RealmConfiguration.Builder(context)
        .name("otherrealm.realm")
        .schemaVersion(5)
        .setModules(new MyOtherSchema())
        .build();

Realm myRealm = Realm.getInstance(myConfig);
Realm otherRealm = Realm.getInstance(otherConfig);
*/

7. Open AndroidManifest.xml and add the MyApplication to <application> tag. Also add the INTERNET permission as we need to make HTTP calls for the images.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.androidhive.info.realm">

<uses-permission android:name="android.permission.INTERNET" />

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

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

8. In the model package add a class named Book.java. Realm data models are created by extending the the RealmObject base class. A Realm data model also supports public, protected and private fields as well as custom methods.

package app.androidhive.info.realm.model;

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

public class Book extends RealmObject {

    @PrimaryKey
    private int id;

    private String title;

    private String description;

    private String author;

    private String imageUrl;

    // Standard getters & setters generated by your IDE…
    public int getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }
}

The @PrimaryKey annotation indicates that this field is set as a Primary key and must not be null.
Also you can use the @Ignore annotation for the fields that should not be persisted to the disk:

@Ignore
private String isbn;

9. Open the layout files of your main activity and add the recyclerView. For my main activity I have three layout files activity_main.xml, content_main.xml and item_books.xml

The activity_main.xml contains the general AppBar, Toolbar and floating action button and includes the content_main.xml layout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:fab="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="enterAlways" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@mipmap/ic_add_white_24dp"
        app:backgroundTint="@color/colorPrimary"
        app:elevation="4dp"
        app:layout_anchor="@+id/recycler"
        app:layout_anchorGravity="bottom|right|end" />

</android.support.design.widget.CoordinatorLayout>

The content_main.xml contains the recyclerView to load the data.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/recycler"
    android:layout_width="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_height="match_parent" />

The item_books.xml contains the CardView with the ImageView and TextView’s for the recycler to display the data.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_books"
    style="@style/AppTheme.Card.Margins"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/image_background"
            android:layout_width="130dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|start" />

        <LinearLayout
            android:id="@+id/layout_partner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingBottom="@dimen/margin_normal">

            <TextView
                android:id="@+id/text_books_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/margin_small"
                android:paddingBottom="@dimen/margin_normal"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:paddingTop="@dimen/margin_large"
                android:textSize="@dimen/text_size_large"
                android:textColor="#555555"
                android:textStyle="bold" />

            <TextView
                android:id="@+id/text_books_author"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:textSize="@dimen/text_size_normal"
                android:textStyle="italic" />

            <TextView
                android:id="@+id/text_books_description"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/margin_small"
                android:maxLines="2"
                android:paddingBottom="@dimen/margin_normal"
                android:paddingLeft="@dimen/margin_large"
                android:paddingRight="@dimen/margin_large"
                android:paddingTop="@dimen/margin_small"
                android:textSize="@dimen/text_size_normal" />

        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>

10. Under the realm package, create a class named RealmController.java. This is a singleton class where we put our realm methods for usage through the app.

package app.androidhive.info.realm.realm;


import android.app.Activity;
import android.app.Application;
import android.support.v4.app.Fragment;

import app.androidhive.info.realm.model.Book;
import io.realm.Realm;
import io.realm.RealmResults;


public class RealmController {

    private static RealmController instance;
    private final Realm realm;

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

    public static RealmController with(Fragment fragment) {

        if (instance == null) {
            instance = new RealmController(fragment.getActivity().getApplication());
        }
        return instance;
    }

    public static RealmController with(Activity activity) {

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

    public static RealmController with(Application application) {

        if (instance == null) {
            instance = new RealmController(application);
        }
        return instance;
    }

    public static RealmController getInstance() {

        return instance;
    }

    public Realm getRealm() {

        return realm;
    }

    //Refresh the realm istance
    public void refresh() {

        realm.refresh();
    }

    //clear all objects from Book.class
    public void clearAll() {

        realm.beginTransaction();
        realm.clear(Book.class);
        realm.commitTransaction();
    }

    //find all objects in the Book.class
    public RealmResults<Book> getBooks() {

        return realm.where(Book.class).findAll();
    }

    //query a single item with the given id
    public Book getBook(String id) {

        return realm.where(Book.class).equalTo("id", id).findFirst();
    }

    //check if Book.class is empty
    public boolean hasBooks() {

        return !realm.allObjects(Book.class).isEmpty();
    }

    //query example
    public RealmResults<Book> queryedBooks() {

        return realm.where(Book.class)
                .contains("author", "Author 0")
                .or()
                .contains("title", "Realm")
                .findAll();

    }
}

The usage of this class is quite simple. Let’s say if we want to get all the objects saved in the Book.class, all we need to do in the wanted activity is call the following getBooks() method from the RealmController.java class:

RealmController.with(this).getBooks()

11. Under the adapters package create the following classes: RealmRecyclerViewAdapater.java, RealmModelAdapter.java, RealmBooksAdapter.java and BooksAdapter.java.

Inside RealmRecyclerViewAdapater.java place the following code:

package app.androidhive.info.realm.adapters;

import android.support.v7.widget.RecyclerView;

import io.realm.RealmBaseAdapter;
import io.realm.RealmObject;

public abstract class RealmRecyclerViewAdapter<T extends RealmObject> extends RecyclerView.Adapter {

    private RealmBaseAdapter<T> realmBaseAdapter;

    public T getItem(int position) {

        return realmBaseAdapter.getItem(position);
    }

    public RealmBaseAdapter<T> getRealmAdapter() {

        return realmBaseAdapter;
    }

    public void setRealmAdapter(RealmBaseAdapter<T> realmAdapter) {

        realmBaseAdapter = realmAdapter;
    }
}

This is a wrapper class that allows a RealmBaseAdapter instance to serve as the data source for a RecyclerView.Adapter

Inside RealmModelAdapter.java place the following code:

package app.androidhive.info.realm.adapters;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import io.realm.RealmBaseAdapter;
import io.realm.RealmObject;
import io.realm.RealmResults;


public class RealmModelAdapter<T extends RealmObject> extends RealmBaseAdapter<T> {

    public RealmModelAdapter(Context context, RealmResults<T> realmResults, boolean automaticUpdate) {

        super(context, realmResults, automaticUpdate);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        return null;
    }
}

In RealmBooksAdaper.java place the following code:

package app.androidhive.info.realm.adapters;

import android.content.Context;

import app.androidhive.info.realm.model.Book;
import io.realm.RealmResults;

public class RealmBooksAdapter extends RealmModelAdapter<Book> {

    public RealmBooksAdapter(Context context, RealmResults<Book> realmResults, boolean automaticUpdate) {

        super(context, realmResults, automaticUpdate);
    }
}

This classes are needed to make the recycler view adapter work with the realm data.

Finally create BooksAdapter.java.

package app.androidhive.info.realm.adapters;

import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;

import app.androidhive.info.realm.R;
import app.androidhive.info.realm.app.Prefs;
import app.androidhive.info.realm.model.Book;
import app.androidhive.info.realm.realm.RealmController;
import io.realm.Realm;
import io.realm.RealmResults;

public class BooksAdapter extends RealmRecyclerViewAdapter<Book> {

    final Context context;
    private Realm realm;
    private LayoutInflater inflater;

    public BooksAdapter(Context context) {

        this.context = context;
    }

    // create new views (invoked by the layout manager)
    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // inflate a new card view
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_books, parent, false);
        return new CardViewHolder(view);
    }

    // replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {

        realm = RealmController.getInstance().getRealm();

        // get the article
        final Book book = getItem(position);
        // cast the generic view holder to our specific one
        final CardViewHolder holder = (CardViewHolder) viewHolder;

        // set the title and the snippet
        holder.textTitle.setText(book.getTitle());
        holder.textAuthor.setText(book.getAuthor());
        holder.textDescription.setText(book.getDescription());

        // load the background image
        if (book.getImageUrl() != null) {
            Glide.with(context)
                    .load(book.getImageUrl().replace("https", "http"))
                    .asBitmap()
                    .fitCenter()
                    .into(holder.imageBackground);
        }

        //remove single match from realm
        holder.card.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {

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

                // Get the book title to show it in toast message
                Book b = results.get(position);
                String title = b.getTitle();

                // All changes to data must happen in a transaction
                realm.beginTransaction();

                // remove single match
                results.remove(position);
                realm.commitTransaction();

                if (results.size() == 0) {
                    Prefs.with(context).setPreLoad(false);
                }

                notifyDataSetChanged();

                Toast.makeText(context, title + " is removed from Realm", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

        //update single match from realm
        holder.card.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View content = inflater.inflate(R.layout.edit_item, null);
                final EditText editTitle = (EditText) content.findViewById(R.id.title);
                final EditText editAuthor = (EditText) content.findViewById(R.id.author);
                final EditText editThumbnail = (EditText) content.findViewById(R.id.thumbnail);

                editTitle.setText(book.getTitle());
                editAuthor.setText(book.getAuthor());
                editThumbnail.setText(book.getImageUrl());

                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setView(content)
                        .setTitle("Edit Book")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

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

                                realm.beginTransaction();
                                results.get(position).setAuthor(editAuthor.getText().toString());
                                results.get(position).setTitle(editTitle.getText().toString());
                                results.get(position).setImageUrl(editThumbnail.getText().toString());

                                realm.commitTransaction();

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

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

    // return the size of your data set (invoked by the layout manager)
    public int getItemCount() {

        if (getRealmAdapter() != null) {
            return getRealmAdapter().getCount();
        }
        return 0;
    }

    public static class CardViewHolder extends RecyclerView.ViewHolder {

        public CardView card;
        public TextView textTitle;
        public TextView textAuthor;
        public TextView textDescription;
        public ImageView imageBackground;

        public CardViewHolder(View itemView) {
            // standard view holder pattern with Butterknife view injection
            super(itemView);

            card = (CardView) itemView.findViewById(R.id.card_books);
            textTitle = (TextView) itemView.findViewById(R.id.text_books_title);
            textAuthor = (TextView) itemView.findViewById(R.id.text_books_author);
            textDescription = (TextView) itemView.findViewById(R.id.text_books_description);
            imageBackground = (ImageView) itemView.findViewById(R.id.image_background);
        }
    }
}

12. Now that everything is set we can add code to the MainActivity.java

> Get realm instance from the RealmController.java
> Setup the recycler. setupRecycler() method is used for this purpose.
> Write some data in realm to be displayed in the recyclerView. setRealmData() method is used for this.
> Refresh the realm instance
> Set the realm adapter, get the realm data and pass it to the adapter

package app.androidhive.info.realm.activity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import app.androidhive.info.realm.app.Prefs;
import app.androidhive.info.realm.R;
import app.androidhive.info.realm.adapters.BooksAdapter;
import app.androidhive.info.realm.adapters.RealmBooksAdapter;
import app.androidhive.info.realm.model.Book;
import app.androidhive.info.realm.realm.RealmController;
import io.realm.Realm;
import io.realm.RealmResults;

public class MainActivity extends AppCompatActivity {

    private BooksAdapter adapter;
    private Realm realm;
    private LayoutInflater inflater;
    private FloatingActionButton fab;
    private RecyclerView recycler;

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

        fab = (FloatingActionButton) findViewById(R.id.fab);
        recycler = (RecyclerView) findViewById(R.id.recycler);

        //get realm instance
        this.realm = RealmController.with(this).getRealm();

        //set toolbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        setupRecycler();

        if (!Prefs.with(this).getPreLoad()) {
            setRealmData();
        }

        // refresh the realm instance
        RealmController.with(this).refresh();
        // get all persisted objects
        // create the helper adapter and notify data set changes
        // changes will be reflected automatically
        setRealmAdapter(RealmController.with(this).getBooks());

        Toast.makeText(this, "Press card item for edit, long press to remove item", Toast.LENGTH_LONG).show();

        //add new item
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                inflater = MainActivity.this.getLayoutInflater();
                View content = inflater.inflate(R.layout.edit_item, null);
                final EditText editTitle = (EditText) content.findViewById(R.id.title);
                final EditText editAuthor = (EditText) content.findViewById(R.id.author);
                final EditText editThumbnail = (EditText) content.findViewById(R.id.thumbnail);

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setView(content)
                        .setTitle("Add book")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                                Book book = new Book();
                                //book.setId(RealmController.getInstance().getBooks().size() + 1);
                                book.setId(RealmController.getInstance().getBooks().size() + System.currentTimeMillis());
                                book.setTitle(editTitle.getText().toString());
                                book.setAuthor(editAuthor.getText().toString());
                                book.setImageUrl(editThumbnail.getText().toString());

                                if (editTitle.getText() == null || editTitle.getText().toString().equals("") || editTitle.getText().toString().equals(" ")) {
                                    Toast.makeText(MainActivity.this, "Entry not saved, missing title", Toast.LENGTH_SHORT).show();
                                } else {
                                    // Persist your data easily
                                    realm.beginTransaction();
                                    realm.copyToRealm(book);
                                    realm.commitTransaction();

                                    adapter.notifyDataSetChanged();

                                    // scroll the recycler view to bottom
                                    recycler.scrollToPosition(RealmController.getInstance().getBooks().size() - 1);
                                }
                            }
                        })
                        .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

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

    public void setRealmAdapter(RealmResults<Book> books) {

        RealmBooksAdapter realmAdapter = new RealmBooksAdapter(this.getApplicationContext(), books, true);
        // Set the data and tell the RecyclerView to draw
        adapter.setRealmAdapter(realmAdapter);
        adapter.notifyDataSetChanged();
    }

    private void setupRecycler() {
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        recycler.setHasFixedSize(true);

        // use a linear layout manager since the cards are vertically scrollable
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recycler.setLayoutManager(layoutManager);

        // create an empty adapter and add it to the recycler view
        adapter = new BooksAdapter(this);
        recycler.setAdapter(adapter);
    }

    private void setRealmData() {

        ArrayList<Book> books = new ArrayList<>();

        Book book = new Book();
        book.setId(1 + System.currentTimeMillis());
        book.setAuthor("Reto Meier");
        book.setTitle("Android 4 Application Development");
        book.setImageUrl("https://api.androidhive.info/images/realm/1.png");
        books.add(book);

        book = new Book();
        book.setId(2 + System.currentTimeMillis());
        book.setAuthor("Itzik Ben-Gan");
        book.setTitle("Microsoft SQL Server 2012 T-SQL Fundamentals");
        book.setImageUrl("https://api.androidhive.info/images/realm/2.png");
        books.add(book);

        book = new Book();
        book.setId(3 + System.currentTimeMillis());
        book.setAuthor("Magnus Lie Hetland");
        book.setTitle("Beginning Python: From Novice To Professional Paperback");
        book.setImageUrl("https://api.androidhive.info/images/realm/3.png");
        books.add(book);

        book = new Book();
        book.setId(4 + System.currentTimeMillis());
        book.setAuthor("Chad Fowler");
        book.setTitle("The Passionate Programmer: Creating a Remarkable Career in Software Development");
        book.setImageUrl("https://api.androidhive.info/images/realm/4.png");
        books.add(book);

        book = new Book();
        book.setId(5 + System.currentTimeMillis());
        book.setAuthor("Yashavant Kanetkar");
        book.setTitle("Written Test Questions In C Programming");
        book.setImageUrl("https://api.androidhive.info/images/realm/5.png");
        books.add(book);


        for (Book b : books) {
            // Persist your data easily
            realm.beginTransaction();
            realm.copyToRealm(b);
            realm.commitTransaction();
        }

        Prefs.with(this).setPreLoad(true);

    }
}

What is happening in this activity is when it is started, if there is no data in the realm, the setRealmData() method creates couple of objects and save it to the realm. After that realm instance is refreshed, the data is called with getBooks() and the adapter is notifyed about the changes:

        // refresh the realm instance
        RealmController.with(this).refresh();
        // get all persisted objects
        // create the helper adapter and notify data set changes
        // changes will be reflected automatically
        setRealmAdapter(RealmController.with(this).getBooks());

Run the app, and you can now see the data displayed in the recycler view.

android-realm-database-tutorial

Performing Write, Update & Delete Operations

13. We have set the app to read the realm data, now let’s do some simple write, update and delete to the data. Under res ⇒ layout, create a layout named edit_item.xml. This layout will be use in a dialog interface for writing and updating.

<?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="match_parent"
    android:orientation="vertical">

    <EditText
    android:id="@+id/title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/activity_horizontal_margin"
    android:hint="Title"
    android:inputType="text" />

    <EditText
        android:id="@+id/author"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:hint="Author"
        android:inputType="text" />

    <EditText
        android:id="@+id/thumbnail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:hint="Image"
        android:inputType="text" />

</LinearLayout>

14. Open again the MainActivity.java and the following code:

//add new item
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                inflater = MainActivity.this.getLayoutInflater();
                View content = inflater.inflate(R.layout.edit_item, null);
                final EditText editTitle = (EditText) content.findViewById(R.id.title);
                final EditText editAuthor = (EditText) content.findViewById(R.id.author);
                final EditText editThumbnail = (EditText) content.findViewById(R.id.thumbnail);

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setView(content)
                        .setTitle("Add book")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                                Book book = new Book();
                                //book.setId(RealmController.getInstance().getBooks().size() + 1);
                                book.setId(RealmController.getInstance().getBooks().size() + System.currentTimeMillis());
                                book.setTitle(editTitle.getText().toString());
                                book.setAuthor(editAuthor.getText().toString());
                                book.setImageUrl(editThumbnail.getText().toString());

                                if (editTitle.getText() == null || editTitle.getText().toString().equals("") || editTitle.getText().toString().equals(" ")) {
                                    Toast.makeText(MainActivity.this, "Entry not saved, missing title", Toast.LENGTH_SHORT).show();
                                } else {
                                    // Persist your data easily
                                    realm.beginTransaction();
                                    realm.copyToRealm(book);
                                    realm.commitTransaction();

                                    adapter.notifyDataSetChanged();

                                    // scroll the recycler view to bottom
                                    recycler.scrollToPosition(RealmController.getInstance().getBooks().size() - 1);
                                }
                            }
                        })
                        .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

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

Here we set and dialog on the floating action button to add new item. Run the following code and try to add some new data. (Note: you might need to uninstall and run the app again for the changes to take place) .

15. In order to make some update and delete actions open BooksAdapter.java and add the following code:

//remove single match from realm
holder.card.setOnLongClickListener(new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {

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

                // Get the book title to show it in toast message
                Book b = results.get(position);
                String title = b.getTitle();

                // All changes to data must happen in a transaction
                realm.beginTransaction();

                // remove single match
                results.remove(position);
                realm.commitTransaction();

                if (results.size() == 0) {
                    Prefs.with(context).setPreLoad(false);
                }

                notifyDataSetChanged();

                Toast.makeText(context, title + " is removed from Realm", Toast.LENGTH_SHORT).show();
                return false;
    }
});

//update single match from realm
holder.card.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View content = inflater.inflate(R.layout.edit_item, null);
                final EditText editTitle = (EditText) content.findViewById(R.id.title);
                final EditText editAuthor = (EditText) content.findViewById(R.id.author);
                final EditText editThumbnail = (EditText) content.findViewById(R.id.thumbnail);

                editTitle.setText(book.getTitle());
                editAuthor.setText(book.getAuthor());
                editThumbnail.setText(book.getImageUrl());

                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setView(content)
                        .setTitle("Edit Book")
                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

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

                                realm.beginTransaction();
                                results.get(position).setAuthor(editAuthor.getText().toString());
                                results.get(position).setTitle(editTitle.getText().toString());
                                results.get(position).setImageUrl(editThumbnail.getText().toString());

                                realm.commitTransaction();

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

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

Here we set delete of a match through long click on the card item and update dialog on click. The removing of an item is very easy. All we need is the bellow code with the position passed to the realm.

// All changes to data must happen in a transaction
        realm.beginTransaction();

        // remove single match
        results.remove(position);
        realm.commitTransaction();

The same happens with the update.

realm.beginTransaction();
                        results.get(position).setAuthor(editAuthor.getText().toString());
                        results.get(position).setTitle(editTitle.getText().toString());
                        results.get(position).setDescription(editDescription.getText().toString());
                        results.get(position).setImageUrl("https://realm.io/assets/RealmSquare.png");

realm.commitTransaction();

Now run the code again (uninstall or clear data if necessary ) and check the changes. Try updating or deleting some items.

android-realm-database-read-write-update-delete

Migration from SQLite

If you have currently have an app that uses SQLite and want to migrate to Realm, there is definitely some work involved. It is not a drop-in change. SQLite prefer a very normalized-form that doesn’t necessarily work the best with Realm. It’s better to rethink your schema and model it as objects.

Once you’ve modified the schema to work well with Realm however, it is much easier to migrate any existing data from SQLite. Just setup a migration (from version 0 to 1 of your Realm database), and in this migration, load your SQLite data into Realm objects and then just save them.

Or, if your data also resides on a remote server, you could just build the Realm database from scratch.
Before adopting Realm though, note that it must be considered as bleeding edge software, with an API that can have breaking changes in future versions.

Ravi is hardcore Android programmer and Android programming has been his passion since he compiled his first hello-world program. Solving real problems of Android developers through tutorials has always been interesting part for him.
  • Ziigic

    Thank you very much, you are awesome.

    • 🙂

      • Narola

        Hi Ravi can you plz provide tutorial for realm with retrofit lib

  • Dia Bader

    I don`t know how to thank you …
    you are really gave an amazing and very very useful Idea ,Tutorial and projects ,
    you are awesome.

  • Åmol Çhavhan

    you always bring something new 😀

  • sina shaloudegi

    Thanks Ravi;
    Do you think we have to say goodbye to Sqlite ?
    is it the time to migrate to OODBs ?

  • Vajeng Patidar

    Thank you Very Much and God bless Ravi, though its not enough…

  • Myth

    Thank you very much Ravi,
    I’m from Vietnamese. my idol !

  • vikash

    Will you please make a tutorial about in app billing ?

  • kid kaito

    Thanks for posts
    Next time you can write post android toturial to Alarms ?
    It ‘s seem very good !

  • Mezooo

    Thank you “Super professional Developer” Really you are a amazing programmer thank you Mr. Ravi.

  • Adel Jaffan

    it’s very interesting, can you publish for us “p2p wifi” courses
    Love from Syria.

  • dedidorez

    Thanks men..

  • Hu Zhong

    How to hide the title bar?

  • Gon Her

    I need help please.

    JSONArray want to dump a database and can not. Not like sending the database.
    This is my json: http://fliveer.com/api/fliveer/home_php/home/realM.php

    This is my test activity.: http://fliveer.com/api/download-center/MainActivity.zip

    Please help.

  • Gon Her

    Because delete my comment? I need help and you eliminate my request for help? Are you a good person?

  • Gon Her

    I have a mysql database and json. You can expand your tutorial and upload this json in REALM please?

    http://fliveer.com/api/fliveer/home_php/home/realM.php

  • sam

    Thank you so much for this tutorial

  • Sandeep Pradhan

    Hey bro how we can use custom images instead of movies images?…..in Image Glide Viewer

  • Murat

    Thanks for tutorial Ravi but i’m getting error.

    Error:(45, 17) error: Getter getId is not associated to any field
    or
    Error:(25, 17) error: Setter setId is not associated to any field

    What could be the reasons for the error?

    • Ahmet Cevahir Çinar

      I am get same error, please help.

  • rose

    hi…thanks for all learnings…

    here is a wrong in BooksAdapter.java there isn’t “Prefs” and give error in running…???

    thanks…!!!

    • Sadegh_khan

      I have this problem too, can you help me Ravi !? meghsi

      • Mouad Ghandi

        Indeed, The problem is that the Class Prefs in file app is missed.

        If you want to get the class you should download the code source, you’ll find it there.

        • Sadegh_khan

          tnx, i had download the code source, but there is not any Prefs Class in app folder!!!

  • David Evhade

    Realm is not working…I can’t build the gradle but when I used version 0.91.0, it built but no more RealmBaseAdapter…It is just throwing errors

    • sizwe

      Ravi is using a RealmRecyclerViewAdapter and to use a RealmRecyclerViewAdapter and/or RealmBaseAdapter, you need to add extra dependencies to the application level build.gradle file.

      dependencies {

      compile ‘io.realm:android-adapters:1.2.2’

      }

      Check Realm documentation under “Working With Android”

      Hope To Have Help You…Cheers

  • Mezooo

    Thank you For Awesome tutorial Mr. Ravi. I really appreciate your efforts.
    I hope to make tutorial about firebase. with Most of features like realtime database connection and GCM

    https://firebase.google.com/

    Feature image:
    https://lh3.googleusercontent.com/Jp5DG28Mj668TyylbnjcCjNvzh-9-IjxT1IixnKrOziswXJzQZZ8GUpRobmQPba0vvINC8c6GymEni3UYcAX3uLVdHFz0Z_x=s888

    • Yeah I am studying Firebase.

      • Jojo

        Bro… go ahead

  • Martin Hurtiš

    I have error on row : this.realm = RealmController.with(this).getRealm();

    Caused by: java.lang.NullPointerException: No default RealmConfiguration was found. Call setDefaultConfiguration() first

    at io.realm.Realm.getDefaultInstance(Realm.java:519)

    at realm.RealmController.(RealmController.java:19)

    Please help me 🙁

    • Kris Lai

      Hi Martin,
      it is because you forgot to add the declaration ‘android:name=”.app.MyApplication”‘ in the manifest file.

      • Martin Hurtiš

        oh, thanks you are amazing 😀

  • Hi Ravi, Thanks for this tutorial.
    After reading that Realm 1.0 has released, I tried to update your demo e.g. to 1.0, but it failed. Can you please provide an update on what changes should be done in gradle file, so that your e.g. can work with Realm 1.0.

    Edit 1 – After some trial and errors, I figured out a way to sync gradle correctly with Realm 1.0. But now, I learnt that, all the adapters are throwing errors. It seems there has been some changes in coding of Realm. Please help.

    • Hi Atul

      I still have to get good knowledge over realm. Please try figuring out the things by yourself.

    • sizwe

      Ravi is using a RealmRecyclerViewAdapter and to use a RealmRecyclerViewAdapter and/or RealmBaseAdapter, you need to add extra dependencies to the application level build.gradle file.

      dependencies {
      compile ‘io.realm:android-adapters:1.2.2’
      }

      Check Realm documentation under “Working With Android”

      Hope To Have Help You…Cheers

      • Hi @sizwe thank you for your help.. unfortunately i won’t be able to test it for next 2 days… will try to test asap.

    • Zhuinden

      I updated the sample to v1.1.1 in my Github repository called “realm-book-example”.

  • WeekendCoder

    Any chance of making a sync adapter tutorial (for contacts, incoming messages etc) 🙂

    • Thanks bro:)

      • WeekendCoder

        Had to ask 🙂 Ravi has the best step by step tutorials for android I could find, and I couldn’t find any good sync adapter tutorial so far.

  • fadi qua

    great example, if i have 2 classes, and the main class has list attribute of second class, how to deal with list attribute, to explain my idea, when i click on the item, it will open detail activity that display information of ” list ” attribute .. ?

  • Sabahat Sana

    hi Ravi,please help me . i use realm with asynctask classes. And my app is crashed.

    return this error:
    Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

  • Saad Saeed

    i want to upload mp3 file into external database through my android application can anybody help.

  • Kuldeep Mishra

    Hi Ravi, What is Pref Class in this tutorial, as you have not mentioned anywhere in this post. And also i try to get source code but always it is giving connection time out after try of 2-3 min…i think may be source code repository is down or something else…please help me to download source code for this post.

  • Please do a sync adapter tutorial

  • Ahmet Cevahir Çinar

    At Book.java file,
    I get an error:
    “Error:(24, 17) error: Setter setId is not associated to any field”
    I look some sources but I dont resolve my problem. Please help.

    • Can you paste your Class code here Book.java

      • Ahmet Cevahir Çinar

        Hi Ravi Tamada,
        I change variable names and this error end.
        For example: Id= book_id
        Thanks for your reply.

        • I need to see your setter / getter method. Anyways use Android Studio code generate option to generate the setter / getter methods.

  • Kuldeep Mishra

    Hi @ravi8x:disqus @disqus_VqKuJF0GgB:disqus ,
    On item delete i’m getting error plz help me…
    Exception:
    java.lang.IllegalStateException: Object is no longer managed by Realm. Has it been deleted?

    I’m using realm 1.0.0. so there no constructor like this RealmBaseAdapter(Context context, RealmResults realmResults, boolean automaticUpdate) is available…no automaticUpdate parameter is there..

    • Zhuinden

      You should not call `adapter.notifyDataSetChanged()` manually after you commit synchronous transaction on the UI thread. You should use a change listener on your results, and notify the adapter in that.

  • Harsh

    Hi Ravi, How to scan business card and fetch information from the card? Do you have any example of that type? If not please develop this kind of example also as this will be more helpful for large amount of people including me as well.
    Thanks.

    • Hi Harsh

      You need to use OCR library to read the text from an image. Please search for android open source OCR library. I don’t have a name to suggest right now.

      • Harsh

        Thanks for the reply Ravi. I have used OCR library but not getting results as expected. I want to develop business card scanning app like CamCard. So is there any way that you can help me?

        • What you mean by not getting results as expected?

          • Harsh

            Hi, When i scan any business card, very few time it gives some of the expected result, otherwise it will displays the junk characters. I have used tesseract library for scanning.

  • Karani Anand

    I would like to say thanks for all your efforts. All the best for Great Future.

    i want to build Dictionary App using Realm database. and i have words in text file format. please any one suggest, how to do?

  • Androider

    Hello, Ravi Tamada!

    I have a problem.. please see it here:

    http://stackoverflow.com/questions/37903176/cannot-pass-parameters-to-super-in-a-classs-constructor-that-extends-realmba

    I try to solve it from days ago, but I didn’t solve it until now! 🙁

  • Androider

    Hello, Ravi Tamada!

    I have a problem.. please see it here:

    http://stackoverflow.com/questions/37903176/cannot-pass-parameters-to-super-in-a-classs-constructor-that-extends-realmba

    I try to solve it from days ago, but I didn’t solve it until now! 🙁

  • Suresh Basnet

    how can i use foreign keys to establish connection between two tables?

    • Zhuinden

      `RealmList`

  • Desarrollo Theworkshop

    new version of realm.io dont have methods reamlm.allobjects, realm.refresh and maybe more

    • Zhuinden

      I’ve updated this guide’s content to the latest Realm in my `realm-book-example` on Github.

      • Collins Mucheru

        @disqus_vnjmcP8nNZ:disqus could you kindly do a blog post that explains your genius (https://github.com/Zhuinden/realm-book-example), or work with Ravi to explain it. Us rookies would really appreciate it. Thanks in advance.

        • Zhuinden

          Technically I wrote the README.MD file for that, and also at the top of the github page, it says this is a repository that accompanies my Medium article called “How to use Realm like a champ”

          • Collins Mucheru

            Yeah, I saw all that before I wrote this comment. It’s just that some of the patterns you’ve used are pretty interesting and seem complex. I’ll have to do quite a bit of reading before I can even begin to comprehend what you’ve written. Thank you for the guide though.

          • Zhuinden

            If anything is unclear, please specify it and I’ll add it to either the readme or the article or I’ll just make a third article that’s more tutorial-y. I’m monitoring my GitHub issues along with Realm-Java’s issues (which I check pretty often), so it’s likely I’ll respond at a reasonable time too

          • Collins Mucheru

            You rewrote the tutorial and used complex concepts that rookies who come to help from Ravi barely understand. Let me break down what I don’t understand using the packages:

            Nothing is happening in the MainActivity.java class, why?

            application: I get what RealmInitialData.java does but the last 3 methods of the class are incomprehensible.

            data.entity: I get what the Book.java Class does, but I can’t for the life of me get what RealmString.java does

            paths.books: BooksActivity is understandable but the moment you implement BooksPresenter.ViewContract I’m lost and I can no longer understand BooksActivity. I’ve used the normal RecyclerViewAdapter so I kinda comprehend BooksAdapter.java. As for BooksAddBookView.java, BooksPresenter.java and BooksAddBookView.java I’m completely lost.

            You seem to be using some interesting ‘veteran’ design pattern where even your presentation of views is modularized. I’m also new to Butterknife, which i think contributes to my scanty understanding of your poetic code.

            NB: Even Realm themselves are stuck showing us examples based on version 0.8.XX (https://realm.io/news/android-recycler-view/)

            Kindly make an effort to explain your work to us so we can also use Realm and Butterknife like champs. Thank you 🙂

          • Zhuinden

            – Actually, lots of things are happening in MainActivity.

            It creates the retained fragment (BooksScopeListener) that reference counts the activity count and opens/closes the Realm, and also creates the presenter instance (because retained fragments survive configuration change.) It also handles all events that have UI stuff going on – showing the “add book” dialog and the “edit book” dialog.

            The AddBookView is the content of the dialog that’s inflated when you click the button that has to show a dialog in R.layout.edit_item’s XML.

            Ravi did the same thing when he calls `inflater.inflate(R.layout.edit_item, null)` and sets this as the content of the dialog, except he set the click listeners manually after inflation, while I used a custom viewgroup instead which handles the binding with ButterKnife by default.

            RealmString is pretty much a placeholder for the workaround of list of primitives (the workaround is `RealmList` ) but I don’t use that anywhere so heed it no mind.

            `RealmInitialData` is a transaction. It inserts the elements into the Realm on first execution. The hashcode/equals just makes it so that every instance of `RealmInitialData` is the same. You’d have to do this for Migration too.

            As for the presenter, well, it’s for your own benefit to delegate UI events to an external class and handle logic there instead of mashing everything in the Activity 🙂 For more info, you should to the GOOGLE CODELABS ANDROID TESTING guide, that is where `.ViewContract` is from.

          • Collins Mucheru

            Thank you. You’ve cleared up for me what I was finding so hard to grasp. Now it’s so much simpler 🙂

          • Collins Mucheru
  • Raja Sekaran

    Hi Ravi,

    Try GreenDao database, it really better than this.

    • Zhuinden

      honestly, this example is overcomplicated and outdated (0.82.1? The latest version is 1.1.1). I’ve updated this guide’s content to the latest Realm in my `realm-book-example` on Github.

  • Imam Kashif

    Hello Ravi, I am using Sugar ORM for most of my apps. Please suggest me which one is better, Realm or Sugar ORM by satyan.

    • Zhuinden

      Well, SugarORM is terrible. So Realm.

  • Nikolai Vasilev

    I cannot understand why you request all these fragments, activities and application in the .with() method parameters. They are not used in the constructor at all…. All the different .with() methods are same and can be removed when the different parameter logic is not making difference

    • Zhuinden

      Yeah, me neither, and it’s not even a proper solution because the Realm instance is never closed.

  • Mouad Ghandi

    Thanks Ravi for this great article,
    Please if you can underscores the utility of Prefs used in both “BooksAdapter” and “MainActivity” as Prefs.with(this).setPreLoad(true);
    and how can we import it ? it still red in my project.

    Best regards,

    • Kiran Benny Joseph

      He is not included Prefs class. anyway thanks for the tutorial

  • Govarthanan Ravi

    Hi can someone tell me what is the difference between adding library as classpath Vs adding it as a dependency

    For example on Realm website they tell that inorder to include realm the following two steps should be followed
    Step:1
    dependencies {
    classpath “io.realm:realm-gradle-plugin:1.1.0”
    }
    Step:2
    apply plugin: ‘realm-android’ on build.gradle file

    but in the above example ravi has asked to include
    compile ‘io.realm:realm-android:0.82.1’

    how do they both differ and in what means

    In other words what is the difference between compile dependencies and classpath dependencies

    • Zhuinden

      Using the `compile` dependency adds the project as a JAR, but adding it on the classpath adds it as a Gradle Plugin (which will add it through AAR)

      • Govarthanan Ravi

        Thanks Zhuinden

  • Viet Nam

    good

  • Vladimir Yerokhin

    Nice article! Thank you!

    • Zhuinden

      It’s actually very outdated.

  • Zhuinden

    This article is outdated and not structured well, so I rewrote it in my `realm-book-example` repository on Github. (I can’t link it because if I do, the comment becomes “Pending”).

    • hello how can i find your github files?

      • Zhuinden

        it’s on github com Zhuinden realm-book-example

        Just add the “.” before the com, and add “/” between the spaces

  • Ganesh Giri

    How can find Realm database ?Any tool to export Realm DB.And view Db.Like SQLITE Browser.

    • Zhuinden

      You just have to copy the file out from the internal storage to somewhere accessible, or you can use stetho-realm (I don’t know if that can export it, but it can definitely view it)

    • Raj

      Only option is to use stetho. Please refer simple video to know about it.
      https://www.youtube.com/watch?v=iyXpdkqBsG8

  • Vishal Kumar

    Hello Ravi ,

    How can get distinct” or “group by” results in realm Database

    • Zhuinden

      Distinct with distinct. Group by is not supported.

  • Please migrate code for realm 2.0.0

    • Zhuinden

      Refer to my example / guide on Github under the name “realm-book-example”, it is up-to-date to Realm 1.2.0, which is close to 2.0.0 compatible apart from the `Realm.init(Context)` call

      • new version of Realm has 6MB!!

        • Zhuinden

          If that is too much, you can do abiSplits, although I think it’s more hassle than it’s worth.

  • Vicky Donor

    You should declare getInstance() method as an instance Method not Class(Static) method it is not good approach.

    • Could you explain why?

      • Vicky Donor

        If we firstly call Controller.getInstance() it will return null so i believe this is not good pattern.you may observe that Controller.with(Application).getRealm() is the better approach .If you want to call in Adapter then Controller.with((Activity)context.getApplicationContext()).getRealm() is another approach.

        • I never found Controller.getInstance() when you add the Application class in Manifest file.

  • How can i use checkbox on RecyclerView without save selected items into database? when i use model which is extends from RealmObject on recyclerview, for every change one of this model must be we use Transaction, 😐 but i dont want to save it to database, its only for getting user selected Items, i can’t resolve this problem

    • Zhuinden

      I know this has been mentioned before, but you can contain temporary state in the adapter itself in a Map, and use onBindViewHolder based on that map rather than the objects directly.

  • Alexandra Klimovich

    Hello, Ravi. I good read. My mobile development team has been using Realm for a couple of years already and to facilitate the Android development we built a Realm Browser for Android. The link to the product is here: http://scand.com/products/realmbrowser/index.html. It’s free and open source. Some expertise on how we built it is here: http://scand.com/blog/2016/10/28/meet-an-efficient-realm-browser-for-android/

    • Hi Alexandra

      The browser looks good 🙂

    • Varad Mondkar

      Hi Alexandra, Nice to see that you have developed Realm Browser for android. But I am facing some problems while implementing it. Can you help me in that? Thank you.

      • Alexandra Klimovich

        Hi Varad, sure! In case there are any issues while working with the library, please write to realm@scand.com. The guys will be happy to assist. Have a great day!

        • Varad Mondkar

          Thank you 🙂

    • rajendra dattatray patil

      how delete particular time thread is delete data in particular filed how it is possible
      ]

  • Amit Khatkar

    hi Ravi,
    Actually i want to know that how to pass data via intent in realm. in this example you are using alertDialog but if we want to start new activity then how to load that data in new activity?

    • Zhuinden

      You need to send the primary key of the object through the intent, and requery it in the other activity.

  • Sajeeb Kumar

    How can I implement Onitemclick from mainactivity?

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    ImageView photo;

    public MyViewHolder(View v) {
    super(v);
    photo = (ImageView) v.findViewById(R.id.Image);

    }

    @Override
    public void onClick(View v) {
    listener.onItemClick(v, getLayoutPosition());
    }
    }

  • Vanraj Vyas

    Hi i am not getting the RealmController Class

    speceially this statements,

    private static RealmController instance;
    private final Realm realm;

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

    • Have you added realm dependencies?

      • Buddha Shrestha

        After adding dependency

        change code.

        public RealmController(Application application) {
        // realm = Realm.getDefaultInstance();
        realm = Realm.getInstance(application);
        }

        it will work

    • Zhuinden

      RealmController will break in multi-threaded environment

  • Tarun Voora

    hi sir,, Its better to mention date on articles.

    • Ken Choong

      this article in 16/5/2016..lolx

  • Eng-Amal Al Kronz

    hi, thanks a lot for this tutorial, and I want to ask how can I display some of realm data and make load more to get more data in list from realm

    • Zhuinden

      Using a RealmRecyclerViewAdapter from realm-android-adapters, or with OrderedRealmCollectionListener

      • Eng-Amal Al Kronz

        I don’t know whats the differance between them, but I wand to make loadmore for data like when using offset in sqlite

        • Zhuinden

          In that case you need to limit the item count in the adapter. Realm does not support “LIMIT” queries because all results are lazily-evaluated.

  • Thiago Porto

    Create an backup/restore with realm.

  • xsinfosol inc

    please provide a realm adapter tutorial with newer version of realm as these methods not work in newer versions

  • xoxoxo

    io.realm.exceptions.RealmException: Primary key constraint broken. Value already exists: 1494937753875, i keep get this error, can someone help me?

    • Tom

      You are trying to create an object on same ID. It means that your 2 requests are made on the same milli-second.

      Add an integer it to be sure like :

      Object o1 = new Object(“title1”);
      Object o2 = new Object(“title2”);
      o1.setId(System.currentTimeMillis());
      o2.setId(System.currentTimeMillis() +1);

  • Aaron Ronoh

    Realm not supporting storing of arrays of primitive data types like int[] or String[]. It’s a serious concern. Any work around?

    • Consider ArrayList / ArrayList.

      • Aaron Ronoh

        Not supported still. Realm docs mentions that I need to write object classes for each of primitive type. Too much unnecessary boilerplate which realm should handle

        • No Lists works very well with Realm. Check once again.

          • Aaron Ronoh

            They only allow the use of RealmList instead of Arraylist/List. However, RealmList or RealmList doesnt work is noted in this issue https://github.com/realm/realm-java/issues/575. I had to switch to couchbase to avoid too much refactoring

          • Alright.

          • I would like to say that please update the tutorial
            import io.realm.RealmBaseAdapter; is’nt supported in latest package

  • Gon Her

    Please, can you update this tutorial? Or create one that downloads information from mysql

  • AbDuL kAdeR

    update the codes please