The document provides information about Realm, a mobile database solution that serves as an alternative to SQLite and Core Data. It summarizes key features of Realm such as being very fast, using object modeling similar to an ORM, automatically refreshing query results, supporting encryption and multiple databases, and providing documentation in Korean. An example use case of Realm in an Instagram photo browsing app called InstagRealm is also described, showing how Realm is used to store and query Instagram API data and update the UI in response to new items.
13. Gson vs Realm
This test is to compare the speed of Gson and Realm with an extremely simple object model. The overall result of the test shows that Realm
performs a little faster than Gson. However, it could show different results in other test conditions. Refer to the appendix for further information.
Gson.toJson
Gson.fromJson
Realm.createObject
copyToRealm
Milisecond
0 300 600 900 1200
15. Model
public class User extends RealmObject {
@PrimaryKey
private String name;
private int age;
@Ignore
private int sessionId;
// + Standard getters & setters generated by your IDE
}
16. Relation
public class Email extends RealmObject {
private String address;
private boolean active;
}
// Many to One
public class Contact extends RealmObject {
private Email email;
}
// Many to Many
public class Contact extends RealmObject {
private RealmList<Email> emails;
}
17. Write
realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();
18. Write
User user = new User("John");
user.setEmail("john@corporation.com");
realm.beginTransaction();
realm.copyToRealm(user); // Copy the object to Realm.
realm.copyToRealmOrUpdate(user);
realm.commitTransaction();
19. Query
// Fluent interface
RealmResults<User> result = realm.where(User.class)
.sort("age");
.beginGroup()
.equalTo("name", "John")
.or()
.equalTo("name", "Peter")
.endGroup()
.findAll();
for (User user : result) {
// do something...
}
22. RealmResults
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
RealmResults<Post> realmResults;
public RecyclerViewAdapter(Realm realm) {
realmResults = realm.where(Post.class).findAll();
}
@Override
public int getItemCount() { return realmResults.size(); }
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Post post = realmResults.get(position);
// do something...
}
}
23. RealmResults
public class UserRecyclerAdapter extends RecyclerView.Adapter<ChatRecyclerAdapter.ViewHolder> {
List<User> users;
public ChatRecyclerAdapter() { /*...*/ }
public void setUsers(List<User> users) { this.users = users; }
@Override
public int getItemCount() { return users == null ? 0 : users.size(); }
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
User user = users.get(position);
/*...*/
}
}
27. Realm Listener
private RealmChangeListener realmListener;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
realmListener = new RealmChangeListener() {
@Override
public void onChange() {
// ... do something with the updates (UI, etc.) ...
}
};
realm.addChangeListener(realmListener);
}
@Override
public void onDestroy() {
super.onDestroy();
realm.removeChangeListener(realmListener);
}
28. Realm Migration
public class Migration implements RealmMigration {
@Override
public long execute(Realm realm, long version) {
// Migrate from version 0 to version 1
if (version == 0) {
Table personTable = realm.getTable(Person.class);
long fistNameIndex = getIndexForProperty(personTable, "firstName");
long lastNameIndex = getIndexForProperty(personTable, "lastName");
long fullNameIndex = personTable.addColumn(ColumnType.STRING, "fullName");
personTable.removeColumn(getIndexForProperty(personTable, "firstName"));
personTable.removeColumn(getIndexForProperty(personTable, "lastName"));
version++;
}
return version;
}
}
https://github.com/realm/realm-java/blob/master/examples/migrationExample
37. Features
Instagram Tag API
ScrollView, ListView, RecyclerView, CardView
Infinite Scroll (Paging), Swipe to Refresh
Retrofit
Gson
EventBus
Royal
Fresco, Butterknife, RecyclerView-Animator, Logger
40. Instagram API
public static void getTag(final Activity activity, final Class<? extends RoyalDatabase> clazz, String next) {
instagramService.getTags("art", accessToken, next, new Callback<TagsCallback>() {
@Override
public void success(TagsCallback tagsCallback, Response response) {
RoyalTransaction.save(clazz, tagsCallback.data);
if (ScrollViewDatabase.class.equals(clazz))
EventBus.getDefault().post(new OnScrollViewUpdateEvent(tagsCallback.pagination.next_max_tag_id, tagsCallback.data));
if (ListViewDatabase.class.equals(clazz))
EventBus.getDefault().post(new OnListViewUpdateEvent(tagsCallback.pagination.next_max_tag_id));
if (RecyclerViewDatabase.class.equals(clazz))
EventBus.getDefault().post(new OnRecyclerViewUpdateEvent(tagsCallback.pagination.next_max_tag_id));
if (CardViewDatabase.class.equals(clazz))
EventBus.getDefault().post(new OnCardViewUpdateEvent(tagsCallback.pagination.next_max_tag_id));
}
@Override
public void failure(RetrofitError error) {
SnackBar.alert(activity, "Please check your network status!");
}
});
}
41. OnEvent
int itemCount = 0;
public void onEvent(OnRecyclerViewUpdateEvent event) {
swipeRefreshLayout.setRefreshing(false);
if (event.isFailed())
return;
next = event.getNext();
if (itemCount < adapter.getItemCount())
adapter.notifyItemRangeInserted(itemCount, adapter.getItemCount() - itemCount);
else
adapter.notifyItemRangeRemoved(itemCount, itemCount - adapter.getItemCount());
itemCount = adapter.getItemCount();
}
42. RecyclerViewAdapter
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
RealmResults<Post> realmResults;
public RecyclerViewAdapter(Realm realm) {
realmResults = realm.where(Post.class).findAll();
}
@Override
public int getItemCount() { return realmResults.size(); }
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Post post = realmResults.get(position);
// do something...
}
}
43. ListViewAdapter
public class ListViewAdapter extends RealmBaseAdapter<Post> implements ListAdapter {
public ListViewAdapter(Context context, RealmResults<Post> realmResults) {
super(context, realmResults, true);
}
static class ViewHolder {
ViewHolder(View view) { /*...*/ }
public void setPost(Post post) { /*...*/ }
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
/* ViewHolder Inflating */
Post post = realmResults.get(position);
viewHolder.setPost(post);
return convertView;
}
}
48. Appendix
Test Device: Galaxy S3
Test Model
public class Contact {
public String address;
public String number;
public boolean active;
}
10000 times iteration per each test.
5 times test per each method
Test Code: https://github.com/Test-Codes/Realm-Java-Benchmark