Android Realm数据库

In this tutorial, we’ll be discussing the basics of Realm Database and implement it in our Android Application for offline data storage.

在本教程中,我们将讨论Realm数据库的基础知识,并将其在我们的Android应用程序中进行离线数据存储。

Android Realm数据库 (Android Realm Database)

Realm is a database that is the perfect alternative to SQLite. It’s is a NoSQL database designed for mobile platform.
Its core consists of a self-contained C++ library. It supports Android and iOS both.

Realm是数据库的完美替代SQLite。 这是专为移动平台设计的NoSQL数据库。
它的核心包括一个自包含的C ++库。 它同时支持Android和iOS。

Pros of Realm

领域的优点

  • Simplicity – Unlike SQLite the code is much shorter and concise. Besides, instead of using SQL, you just need to deal with objects and object trees in Realm.

    简洁性 –与SQLite不同,代码更短而简洁。 此外,无需使用SQL,您只需要在Realm中处理对象和对象树。
  • Speed – Despite having a complex algorithm underneath, Realm performs CRUD operations faster. Obtaining objects is very fast since there is no deserialization

    速度 –尽管底层算法复杂,但Realm可以更快地执行CRUD操作。 因为没有反序列化,所以获取对象非常快
  • Live Objects – Realm has a no copy behaviour. All fetches are lazy, and the data is never copied until you perform some operations on them.
    So till then from a query, all that you get is pointers to data. Hence all objects received from Realm are proxy to the database. Due to this, zero copy is achieved. Whenever you need to access the data you will always get the latest value.

    Live Objects – Realm没有复制行为。 所有提取都是延迟的,除非对它们执行某些操作,否则永远不会复制数据。
    因此,在此之前,从查询中获得的只是数据指针。 因此,从Realm接收的所有对象都是数据库的代理。 因此,实现了零拷贝。 每当您需要访问数据时,您将始终获得最新的价值。
  • Great Documentation – Realm documentation is clear and the community support is great.

    出色的文档 -领域文档清晰明了,社区支持也很棒。
  • JSON Support Built-in – Realm has JSON support. You can directly set data from JSON without the need to create model classes.

    内置JSON支持 – Realm具有JSON支持。 您可以直接从JSON设置数据,而无需创建模型类。
  • Security – You can secure the database using encryption.

    安全性 –您可以使用加密保护数据库。
  • Reactive Programming – You can observe changes in the database and update the UI accordingly. Using RxJava along with Realm just makes it a lot more simple and fun.

    响应式编程 –您可以观察数据库中的更改并相应地更新UI。 与Realm一起使用RxJava会使它变得更加简单和有趣。
  • Built-in Adapters – Realm has Adapter classes for the Android UI components.

    内置适配器 – Realm具有适用于Android UI组件的适配器类。


  • Cons of Realm



    领域的缺点

  • No Auto-increment – You cannot auto-increment values in Realm.

    无自动递增 –您无法在Realm中自动递增值。
  • Restrictions on Model classes – Besides the getter setter methods you cannot override methods like hashcode and equals in the Realm Model classes.

    对模型类的限制 –除了getter setter方法外,您不能覆盖诸如Realm Model类中的哈希码和equals之类的方法。
  • Threading – Real model classes can’t be passed from one thread to another. Hence you’ll have to query the class again on the different thread.

    线程 –实模型类不能从一个线程传递到另一个线程。 因此,您将不得不在不同的线程上再次查询该类。
  • 在Android中配置领域 (Configuring Realm in Android)

    Add the following classpath in your root build.gradle file:

    在根build.gradle文件中添加以下类路径:

    buildscript {
        ...
        dependencies {
            ...
            classpath 'io.realm:realm-gradle-plugin:3.2.1'
        }
    }

    Add the following plugin to the app’s build.gradle

    将以下插件添加到应用的build.gradle

    apply plugin: 'realm-android'

    Creating a Realm Instance

    创建一个领域实例

    To create a Realm instance we do the following:

    要创建一个Realm实例,请执行以下操作:

    Realm mRealm = Realm.getInstance(context);

    We can also pass a RealmConfiguration instance inside the getInstance()

    我们还可以在getInstance()内传递RealmConfiguration实例。

    RealmConfiguration config =
                    new RealmConfiguration.Builder()
                            .name("test.db")
                            .schemaVersion(1)
                            .deleteRealmIfMigrationNeeded()
                            .build();

    Creating Realm Model class

    创建领域模型类

    To create Model classes, extend them with RealmObject.
    Primary keys can be of String or integer type and are annotated with @PrimaryKey annotation.

    要创建Model类,请使用RealmObject对其进行RealmObject
    主键可以是String或整数类型,并带有@PrimaryKey注释。

    Following are some annotations commonly used on Realm Model classes:

    以下是领域模型类上常用的一些注释:

    • @PrimaryKey

      @首要的关键
    • @Required – Cannot be null

      @Required –不能为空
    • @Index – Add this on fields you are using in Query. It makes the queries 4X faster.

      @Index –在查询中使用的字段上添加它。 它使查询速度提高了4倍。
    • @Ignore

      @忽视

    将数据写入领域 (Writing Data to Realm)

    You can write data to Realm in the following ways:

    您可以通过以下方式将数据写入Realm:

    Realm realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    realm.copyToRealm(realmModelInstance)
    realm.commitTransaction();

    There is a problem with the above approach though. It doesn’t cancel the transaction if failed.
    Hence it is not the recommended way to insert data into the Database.

    但是,上述方法存在问题。 如果失败,它不会取消交易。
    因此,不建议将数据插入数据库。

    The method executeTranscation or executeTranscationAsync automatically handle the cancel transaction.

    方法executeTranscationexecuteTranscationAsync自动处理取消事务。

    Realm realm = Realm.getDefaultInstance();
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.insertOrUpdate(realmModelInstance);
            }
        });

    Also, we can add a try-catch inside the executeTranscation to catch exceptions. Try-catch is ignored by the earlier approach though.

    另外,我们可以在executeTranscation内部添加一个try-catch来捕获异常。 但是,较早的方法忽略了try-catch。

    insertOrUpdate or insertOrUpdatecopyToRealmOrUpdate are used to insert if the primary key doesn’t exist or update the current object if the primary key exists. copyToRealmOrUpdate进行插入;如果主键存在,则用于更新当前对象。

    从领域阅读 (Read From Realm)

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

    Again it’s a good practice to use this inside the execute method.

    同样,在execute方法中使用此方法也是一个好习惯。

    从领域删除 (Delete From Realm)

    mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    RealmResults<RealModelClass> results = realm.where(RealModelClass.class).findAll();
                    results.deleteAllFromRealm();
                }
            });

    Following are the other methods that can be used to delete the results:

    以下是可用于删除结果的其他方法:

    RealmList is a built-in collection of RealmObjects and is used for model one-to-many relationships.

    RealmListRealmList的内置集合,用于模型一对多关系。

    RealmList cannot support non-realm objects(such as Long, String, Integer).

    RealmList无法支持非领域对象(例如Long,String,Integer)。

    In the following section, we’ll be creating a basic Android Application which uses Realm and performs CRUD operations.

    在下一节中,我们将创建一个基本的Android应用程序,该应用程序使用Realm并执行CRUD操作。

    项目结构 (Project Structure)

    (Code)

    The code for the activity_main.xml layout is given below:

    下面给出了activity_main.xml布局的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:orientation="horizontal"
        android:weightSum="2"
        tools:context=".MainActivity">
    
    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">
    
            <EditText
                android:id="@+id/inName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Name" />
    
            <EditText
                android:id="@+id/inAge"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Age"
                android:inputType="number" />
    
            <EditText
                android:id="@+id/inSkill"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Skill" />
    
    
            <Button
                android:id="@+id/btnAdd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="ADD" />
    
    
            <TextView
                android:id="@+id/textViewEmployees"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Result:" />
    
    
            <Button
                android:id="@+id/btnRead"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="READ" />
    
            <Button
                android:id="@+id/btnUpdate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="UPDATE" />
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical">
    
            <TextView
                android:id="@+id/txtFilterByAge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Result:" />
    
            <Button
                android:id="@+id/btnFilterByAge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="EMPLOYEE OVER 25" />
    
    
            <TextView
                android:id="@+id/txtFilterBySkill"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Result:" />
    
    
            <Button
                android:id="@+id/btnDelete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="DELETE BY NAME" />
    
            <Button
                android:id="@+id/btnDeleteWithSkill"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="DELETE ALL WITH SKILL" />
    
        </LinearLayout>
    
    </LinearLayout>

    Inside the MyApplication.java is where we initialise our Realm.

    在MyApplication.java中,是我们初始化领域的地方。

    package com.journaldev.androidrealmdatabase;
    
    import android.app.Application;
    
    import io.realm.Realm;
    import io.realm.RealmConfiguration;
    
    public class MyApplication extends Application {
    
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            Realm.init(getApplicationContext());
    
    
            RealmConfiguration config =
                    new RealmConfiguration.Builder()
                            .deleteRealmIfMigrationNeeded()
                            .build();
    
            Realm.setDefaultConfiguration(config);
        }
    }

    The code for the Employee.java class is given below:

    Employee.java类的代码如下:

    package com.journaldev.androidrealmdatabase;
    
    import io.realm.RealmList;
    import io.realm.RealmObject;
    import io.realm.annotations.PrimaryKey;
    import io.realm.annotations.Required;
    
    public class Employee extends RealmObject {
    
    
        public static final String PROPERTY_NAME = "name";
        public static final String PROPERTY_AGE = "age";
    
        @PrimaryKey
        @Required
        public String name;
        public int age;
    
        public RealmList<Skill> skills;
    }

    The code for the Skill.java class is given below:

    下面给出了Skill.java类的代码:

    package com.journaldev.androidrealmdatabase;
    
    import io.realm.RealmObject;
    import io.realm.annotations.PrimaryKey;
    import io.realm.annotations.Required;
    
    
    public class Skill extends RealmObject {
    
        public static final String PROPERTY_SKILL = "skillName";
    
        @PrimaryKey
        @Required
        public String skillName;
    }

    The code for the MainActivity.java is given below:

    MainActivity.java的代码如下:

    package com.journaldev.androidrealmdatabase;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import io.realm.Realm;
    import io.realm.RealmList;
    import io.realm.RealmResults;
    import io.realm.exceptions.RealmPrimaryKeyConstraintException;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
    
        Button btnAdd, btnRead, btnUpdate, btnDelete, btnDeleteWithSkill, btnFilterByAge;
        EditText inName, inAge, inSkill;
        TextView textView, txtFilterBySkill, txtFilterByAge;
        Realm mRealm;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initViews();
    
            mRealm = Realm.getDefaultInstance();
        }
    
        private void initViews() {
            btnAdd = findViewById(R.id.btnAdd);
            btnAdd.setOnClickListener(this);
            btnRead = findViewById(R.id.btnRead);
            btnRead.setOnClickListener(this);
            btnUpdate = findViewById(R.id.btnUpdate);
            btnUpdate.setOnClickListener(this);
            btnDelete = findViewById(R.id.btnDelete);
            btnDelete.setOnClickListener(this);
            btnDeleteWithSkill = findViewById(R.id.btnDeleteWithSkill);
            btnDeleteWithSkill.setOnClickListener(this);
            btnFilterByAge = findViewById(R.id.btnFilterByAge);
            btnFilterByAge.setOnClickListener(this);
            textView = findViewById(R.id.textViewEmployees);
            txtFilterBySkill = findViewById(R.id.txtFilterBySkill);
            txtFilterByAge = findViewById(R.id.txtFilterByAge);
    
            inName = findViewById(R.id.inName);
            inAge = findViewById(R.id.inAge);
            inSkill = findViewById(R.id.inSkill);
        }
    
        @Override
        public void onClick(View view) {
    
            switch (view.getId()) {
                case R.id.btnAdd:
                    addEmployee();
                    break;
                case R.id.btnRead:
                    readEmployeeRecords();
                    break;
                case R.id.btnUpdate:
                    updateEmployeeRecords();
                    break;
                case R.id.btnDelete:
                    deleteEmployeeRecord();
                    break;
                case R.id.btnDeleteWithSkill:
                    deleteEmployeeWithSkill();
                    break;
                case R.id.btnFilterByAge:
                    filterByAge();
                    break;
            }
        }
    
        private void addEmployee() {
    
            Realm realm = null;
            try {
                realm = Realm.getDefaultInstance();
                realm.executeTransaction(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
    
    
                        try {
    
    
                            if (!inName.getText().toString().trim().isEmpty()) {
                                Employee employee = new Employee();
                                employee.name = inName.getText().toString().trim();
    
                                if (!inAge.getText().toString().trim().isEmpty())
                                    employee.age = Integer.parseInt(inAge.getText().toString().trim());
    
    
                                String languageKnown = inSkill.getText().toString().trim();
    
                                if (!languageKnown.isEmpty()) {
                                    Skill skill = realm.where(Skill.class).equalTo(Skill.PROPERTY_SKILL, languageKnown).findFirst();
    
                                    if (skill == null) {
                                        skill = realm.createObject(Skill.class, languageKnown);
                                        realm.copyToRealm(skill);
                                    }
    
                                    employee.skills = new RealmList<>();
                                    employee.skills.add(skill);
                                }
    
                                realm.copyToRealm(employee);
                            }
    
                        } catch (RealmPrimaryKeyConstraintException e) {
                            Toast.makeText(getApplicationContext(), "Primary Key exists, Press Update instead", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            } finally {
                if (realm != null) {
                    realm.close();
                }
            }
        }
    
    
        private void readEmployeeRecords() {
    
    
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
    
                    RealmResults<Employee> results = realm.where(Employee.class).findAll();
                    textView.setText("");
                    for (Employee employee : results) {
                        textView.append(employee.name + " age: " + employee.age + " skill: " + employee.skills.size());
                    }
                }
            });
    
    
        }
    
        private void updateEmployeeRecords() {
    
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
    
    
                    if (!inName.getText().toString().trim().isEmpty()) {
    
    
                        Employee employee = realm.where(Employee.class).equalTo(Employee.PROPERTY_NAME, inName.getText().toString()).findFirst();
                        if (employee == null) {
                            employee = realm.createObject(Employee.class, inName.getText().toString().trim());
                        }
                        if (!inAge.getText().toString().trim().isEmpty())
                            employee.age = Integer.parseInt(inAge.getText().toString().trim());
    
                        String languageKnown = inSkill.getText().toString().trim();
                        Skill skill = realm.where(Skill.class).equalTo(Skill.PROPERTY_SKILL, languageKnown).findFirst();
    
                        if (skill == null) {
                            skill = realm.createObject(Skill.class, languageKnown);
                            realm.copyToRealm(skill);
                        }
    
    
                        if (!employee.skills.contains(skill))
                            employee.skills.add(skill);
    
                    }
                }
            });
        }
    
        private void deleteEmployeeRecord() {
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    Employee employee = realm.where(Employee.class).equalTo(Employee.PROPERTY_NAME, inName.getText().toString()).findFirst();
                    if (employee != null) {
                        employee.deleteFromRealm();
                    }
                }
            });
        }
    
        private void deleteEmployeeWithSkill() {
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
    
                    RealmResults<Employee> employees = realm.where(Employee.class).equalTo("skills.skillName", inSkill.getText().toString().trim()).findAll();
                    employees.deleteAllFromRealm();
                }
            });
        }
    
    
        private void filterByAge() {
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
    
                    RealmResults<Employee> results = realm.where(Employee.class).greaterThanOrEqualTo(Employee.PROPERTY_AGE, 25).findAllSortedAsync(Employee.PROPERTY_NAME);
    
                    txtFilterByAge.setText("");
                    for (Employee employee : results) {
                        txtFilterByAge.append(employee.name + " age: " + employee.age + " skill: " + employee.skills.size());
                    }
                }
            });
        }
    
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mRealm != null) {
                mRealm.close();
            }
        }
    }

    Don’t forget to close the Realm instance!

    不要忘记关闭Realm实例!

    When you click update with a different Skill that doesn’t exist, it creates that and adds it to the RealmList.

    当您单击不存在的其他技能进行更新时,它将创建该技能并将其添加到RealmList中。

    The output of the above application in action is given below:

    上面应用程序的输出如下:

    That brings an end to this tutorial. You can download the project from the link below:

    这样就结束了本教程。 您可以从下面的链接下载项目:

    翻译自: https://www.journaldev.com/23357/android-realm-database

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值