这是 Realm 移动数据库的系类文章的第一部分;它强调了 Realm 数据引擎的优点和开发者可以使用的原生类。
Realm 移动数据库是一种新型的移动数据库,它是全新的,从零开始研发的,它能使得当今的移动开发如虎添翼。
常常会有这样的误解,Realm 是构建在一个现有的技术上的,或者是另外一个库的重写。毕竟,不像服务器端的数据库,客户端没有多少创新。
在这篇文章中,我们将看看 Realm 和其他技术与众不同的地方。如果你听说过 Realm,但是又不很了解它特别的地方,这篇博客就非常适合你。
看看这些公司还有成千上万的企业都信任 Realm 来支持它们的应用的原因,它们的应用都有超过 10 亿用户了。
数据层库和 ORMs
被你称作 “数据库程序库” 的东西指的是 — 使用某种存储引擎的第三方程序库,它可以提供一个 现代/功能性/多样的 (选你喜欢的) 方式来访问你的数据层。
你可以使用 Swift 或者 Java 库来访问你的 SQLite 存储,采用一种更为现代的方式,比如 generics 和 structs。但是存储引擎仍然使用 SQLite 来完成所有的磁盘读写操作。
而且,你使用的第三方库仍然需要把你的本地数据结构转换成某种数据格式,执行背后的 SQL 查询,然后把你的数据转换成 SQL 表的一行。
如果你使用一个成熟的 ORM,你几乎总是需要大量的后台运行操作。一个 ORM 会持续地把你的对象转换成中间格式,然后运行 SQL 语句来和 SQLite 文件打交道。任何时候你访问一个和你正在工作的对象相关的对象,ORM 会把它转换成一个 JOIN
SQL 查询,在一个查询表上执行它,然后在另外一个表上找到对应的记录,那个表存储着相关的对象。
简单的数据访问都会隐藏着大量的工作。它不仅仅消耗了 CPU 和磁盘时间,也会 急剧 变慢。这意味着你不得不把这些工作放到主线程之外完成,而且引入合适的线程技术,现在你的代码变得非常复杂了,仅仅只是为了得到数据。
Realm 不是重复现在的技术
看看现在的解决方案和上面提到的缺点, Realm 小组决定自己实现,构建性能优越的 存储引擎。
Realm 移动数据库因此 和 SQLite 没有任何关系 也不是另外一个 SQL 数据库;它的目标就是去解决这些领域里面的已知问题。但是 Realm 移动数据库也 不是一个键-值存储 类型,这种存储类型在某些情况下非常棒,但是开发者真的很想直接和本地对象打交道。
最后,Realm 移动数据库 也不是一个 ORM。ORM 把 SQL 数据库的表结构中平的数据转换成了对象图,这样它们能被本地代码使用了。 Realm 的客制化存储引擎不需要把数据转换成对象图,所以它不需要 ORM。
Realm 数据库 直接存储对象 在磁盘上,当然需要最少的类型和结构的转换。英文它没有映射关系或者其它动态解读实体,Realm 移动数据库能够从内存到磁盘非常迅速地操作对象。
事实上,这是 Realm 移动数据库的一个标志性特性:你可以在主线程里面读写!你不用担心这会阻塞你的 UI。(这背后是有原因的,我们不是魔术师。 🎩)
Realm 的核心是用非常快的 C++ 写的,它把 C++ 对象映射到磁盘上。因为它是和 SDK 一起开发的,它的 API 和行为和移动应用使用数据的方式高度耦合,这样你可以很容易理解它的工作方式。
这种高度联系的方式让人想起 iOS:苹果制造 iPhone 硬件,然后给开发者提供最好的 SDK 来最大程度使用硬件。这就是为什么在一个很长的联系人列表上滑动的时候永远都不会掉帧,即使硬件不如其他设备性能强劲的情况下也是如此。
更进一步,通过一个坚实的,可兼容的,多平台的 C++ 内核, Realm 有着在任何地方都运行很好的潜力,它不会限制在某一个平台或者供应商上。
你可能会开始担心这篇演讲会是关于 C++ 的,你也许会问 “那么,使用 Realm 我需要了解 C++ 吗?” 谢天谢地,你不需要,这是因为……
一个坚实的核心使用你的语言
Realm 移动数据库支持 5 种 SDK,API 层非常轻量,这使得你可以用任何移动编程语言来使用核心 API。
每一个 SDK 被设计成能使用开发者熟悉的语言和平台特性。让我们看看那基本的 Realm Swift 和 Realm Java。
我们从 Realm Swift 开始,你可能会定义一个对象:
class Repository: Object {
dynamic var id: Int = 0
dynamic var stars: Int = 0
dynamic var url: String = ""
dynamic var name: String?
dynamic var favorite: Favorite?
}
然后查询一些对象:
let repos = realm.objects(Repository.self)
.filter("name contains[c] %@", searchTerm)
这些代码使用了 Swift 的 generics 来泛型结果集,而且它使用了苹果的 NSPredicate
来允许你能使用你熟悉的语法来查询。一个函数式的方法链条在 Swift 编程者中间是非常流行的。使用诸如 map
, filter
和 sort
的方法在独立的集合类型上,所以 Realm 的集合类型也提供了类似的 API。
现在让我们看看 Realm Java 里面的同样的概念。你可以在 Java 里面定义同样的对象:
public class Repository extends RealmObject {
@PrimaryKey
private Int id;
private Int stars;
public Int getId() { return id; }
public void setId(Int id) { this.id = id; }
public Int getStars() { return stars; }
public void setStars(Int id) { this.stars = stars; }
//etc.
}
现在你可以在安卓上查询这些 Repository
对象:
RealmResults<Repository> results = realm.where(Repository.class)
.contains("name", searchTerm).findAll();
这段 Java 代码和刚才的 Swift 代码完成的是同样的事情。但是 API 不是和 Swift SDK 中的完全一样。这段代码和一个安卓应用的剩下的代码非常吻合,因为它符合安卓的风格。
成熟的类
最后一个要点,Realm 对象是成熟的类。你可以使用你喜欢的任何编程语言的工具来完成你想做的事情,非常快!
你可以构建这样的功能,为不同的简单的计算属性自动生成数值:
class Repository: Object {
dynamic var stars: Int = 0
var starsDecorated: String {
return "\(stars) ⭐️"
}
}
接下来封装业务逻辑:
extension Repository {
static func all(searchTerm: String? = nil) -> Results<Repository> {
let realm = try! Realm()
return realm.objects(Repository.self)
.filter("name contains[c] %@", searchTerm ?? "")
.sorted(byProperty: "stars", ascending: false)
}
}
如果你想看看完整的成熟的 Realm 对象,请看 GitHub 上的 **这篇文章的配套项目 ** 。
例子中的 Repository
类功能:
- 单一数据属性 (
id
,stars
) - 相关对象 (
favorite
) - 计算属性 (
nameDecorated
) - 动态属性 (
avatarUrl
) - 客制化
init
- 索引 (
primaryKey()
,indexedProperties()
) - Metadata (
ignoredProperties()
) - 单一实体函数 (
all(searchTerm:)
,add(repos:)
, andtoggle(favorite:)
)
我们希望你喜欢你看到的东西!
我们触及到了 Realm 移动数据库的伟大的功能。它定制的数据引擎给你的程序的性能和健壮性打下了坚实的基础。
这篇文章使用了 Swift 作为例子,但是 Realm 移动数据库在别的语言里面也是非常容易使用的。
你可以看看这些在线文档:
- Realm Java on Android,
- C# 开发者文档 Realm Xamarin,
- 使用 [React Native] 完成跨平台开发(https://realm.io/docs/javascript/latest/).
这篇文章仅仅是 Realm 移动数据库系类文章的开篇,希望你能喜欢。下一次,我们将看看一些 the RealmSwift API类,这些类使你能够很容易地构建性能优越的应用。
请看下篇! 👋
About the content
This content has been published here with the express permission of the author.