Android Realm数据库
在本教程中,我们将讨论Realm数据库的基础知识,并将其在我们的Android应用程序中进行离线数据存储。
Android Realm数据库
Realm是数据库的完美替代SQLite。
这是专为移动平台设计的NoSQL数据库。
它的核心包括一个自包含的C ++库。
它同时支持Android和iOS。
领域的优点
简洁性–与SQLite不同,代码更短,更简洁。
此外,无需使用SQL,您只需要在Realm中处理对象和对象树。速度–尽管底层算法复杂,但Realm可以更快地执行CRUD操作。
因为没有反序列化,所以获取对象非常快Live Objects – Realm没有复制行为。
所有提取都是延迟的,除非对它们执行某些操作,否则永远不会复制数据。
因此,在此之前,从查询中获得的只是数据指针。
因此,从Realm接收的所有对象都是数据库的代理。
因此,实现了零拷贝。
每当您需要访问数据时,您将始终获得最新的价值。
出色的文档-领域文档清晰明了,社区支持也很棒。
内置JSON支持– Realm具有JSON支持。
您可以直接从JSON设置数据,而无需创建模型类。安全性–您可以使用加密保护数据库。
响应式编程–您可以观察数据库中的更改并相应地更新UI。
将RxJava与Realm一起使用只会使其变得更加简单和有趣。内置适配器– Realm具有适用于Android UI组件的适配器类。
领域的缺点
无自动递增–您无法在Realm中自动递增值。
对模型类的限制–除了getter setter方法外,您无法覆盖诸如Realm Model类中的hashcode和equals之类的方法。
线程处理–不能将真实模型类从一个线程传递到另一个线程。
因此,您将不得不在其他线程上再次查询该类。
在Android中配置领域
在您的根目录build.gradle中添加以下类路径:
buildscript {
...
dependencies {
...
classpath 'io.realm:realm-gradle-plugin:3.2.1'
}
}
将以下插件添加到应用的" build.gradle"中
apply plugin: 'realm-android'
创建一个领域实例
要创建一个Realm实例,请执行以下操作:
Realm mRealm = Realm.getInstance(context);
我们也可以在getInstance()内部传递一个RealmConfiguration实例。
RealmConfiguration config =
new RealmConfiguration.Builder()
.name("test.db")
.schemaVersion(1)
.deleteRealmIfMigrationNeeded()
.build();
创建领域模型类
要创建Model类,请使用RealmObject对其进行扩展。
主键可以是String或者整数类型,并带有@ PrimaryKey注释。
以下是领域模型类上常用的一些注释:
@首要的关键
@Required –不能为空
@Index –在查询中使用的字段上添加它。
它使查询速度提高了4倍。@忽视
将数据写入领域
您可以通过以下方式将数据写入Realm:
Realm realm = Realm.getDefaultInstance(); realm.beginTransaction(); realm.copyToRealm(realmModelInstance) realm.commitTransaction();
但是,上述方法存在问题。
如果失败,它不会取消交易。
因此,不建议将数据插入数据库。
方法" executeTranscation"或者" executeTranscationAsync"会自动处理取消交易。
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(realmModelInstance);
}
});
同样,我们可以在executeTranscation内部添加一个try-catch来捕获异常。
但是,较早的方法忽略了try-catch。
如果主键不存在,则使用" insertOrUpdate"或者" copyToRealmOrUpdate"进行插入;如果主键存在,则用于更新当前对象。
从领域阅读
RealmResults<RealModelClass> results = realm.where(RealModelClass.class).findAll();
同样,在execute方法中使用此代码也是个好习惯。
从领域删除
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmResults<RealModelClass> results = realm.where(RealModelClass.class).findAll();
results.deleteAllFromRealm();
}
});
以下是可用于删除结果的其他方法:
RealmList是RealmObjects的内置集合,用于模型一对多关系。
RealmList无法支持非领域对象(例如Long,String,Integer)。
在下一节中,我们将创建一个基本的Android应用程序,该应用程序使用Realm并执行CRUD操作。
代码
下面给出了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>
在MyApplication.java内部,是我们初始化领域的地方。
package com.theitroad.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);
}
}
Employee.java类的代码如下:
package com.theitroad.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;
}
下面给出了Skill.java类的代码:
package com.theitroad.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;
}
MainActivity.java的代码如下:
package com.theitroad.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();
}
}
}
不要忘记关闭Realm实例!
当您单击不存在的其他技能进行更新时,它会创建该技能并将其添加到RealmList。

