也许你并没有听说过 Realm ,这是一个面向安卓(亦面相iOS)的移动端数据库技术。和SQLite不同,它允许你在持久层直接和数据对象工作。在它之上是一个函数式风格的查询api,众多的努力让它比传统的SQLite 操作更快 。基于这些原因让我决定试试Realm 。
blob.png
大约一年前,当我第一次使用Realm 的时候,给我的第一印象非常不错。我需要保持一些用户数据在手机本地,但是SharedPreferences用起来有点复杂了。Realm允许我用快速干净的代码里完成这件事情。它完全不需要像SQLite那样自己手动写额外的代码。
我接下来的一个项目在缺少网络连接的时候需要一个比较复杂的离线模式。从网络抓取的数据必须保存在手机本地。我决定完全使用Realm 并观察它随项目增大是如何扩大的。
而我很快发现Realm让数据模型的工作成了一种负担。它有几个限制以至于我必须在整个代码基础上做处理。结果我尝试在Realm之上抽象出另外一层来减轻这种限制。
定义对象
为了说明这些限制,让我们从简单的Person对象开始:
public class Person extends RealmObject {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
注意我们必须直接继承自RealmObject。这阻碍我们利用数据模型中的任意类型的继承。
并且我们还不能定义除setters 和 getters之外的实例方法。如果你想重写equals 或者toString`那么你就别想了。这样导致的另外一个后果就是我们只能局限于使用标记接口模式(marker interfaces) (注解也是可以的 )。
不仅仅被限制于setters 和 getters,实际上我们还必须提供它们。因此我们的数据对象是不可变的!另外,setters 和 getters方法只是为Realm替换自己实现的代理方法。它不能操作数据,跑出异常,或者打印日志。
虽然我们可以提供一个非默认的构造函数,但是我们必须保证存在一个空的构造函数。如果你想用一个builder 或者工厂方法来作为实例化的唯一途径,那么这种限制就成了一个问题。稍后我们将看看如何用Realm创建对象。
在我们能持有的field类型方面,也有一些限制。所有的基本数据类型以及它们的封装类型都能支持,包括String, Date, 和byte[]`。但是对于其它类型,为了被持久化,必须继承自RealmObject。Lists可以用RealmList来支持。
但是也仅此而已。如果我们想使用枚举而不是int,是没有办法的(找到一个使用@IntDef的理由了)。我们还不能使用集合类型,比如Set和Map。
创建和更新对象
为了创建一个Person类的实例,我们必须做如下事情:
Realm realm = Realm.getInstance(context);
realm.beginTransaction();
Person person = realm.createObject(Person.class);
person.setName("John");
person.setAge(25);
realm.commitTransaction();
你会注意到我们必须包裹一下Person 对象,同时任何对它的修改都在一个transaction 中。如果我们能在transaction 之外做这件事情并在我们准备好的时候持久化它,就要灵活得多。而现在我们在想要创建或者更新我们对象的任何时候都要卡在写额外的Realm 代码上面。
之前我提过我们可以定义一个非默认的构造函数。比如,对于Person我们可能有一个带有name 和 age的构造函数:
public class Person extends RealmObject {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
// required empty public constructor
}
// setters and getters
...
}
我们不再需要直接调用setters :
Person person = new Person("John", 25);
realm.beginTransaction();
Person realmPerson = realm.copyToRealm(person);
realm.commitTransaction();
这让我们省去了一些写额外代码的时间,但是仍然受限于transaction。
Mitigating These Issues
为了避免在基础代码中处理这些限制,我为数据对象定义了两套类: POJOs (普通对象)和Realm 对象。然后我们创建了一个能在两者之间映射的abstraction 。
这是可行的,但是有两个主要的问题。第一个是当你持有许多不同类型的对象时,你需要许多代码来映射这些类。管理这些是很痛苦的而且这也很容易产生bug。 对象映射的概念以及它存在的问题都不是什么新东西了。
第二个就是我觉得这有违最初使用Realm的目的。能在持久层直接使用对象是它的主要好处。如果我们为了使用POJO而必须在Realm 之上创建抽象,那么它相比SQLite或者像 DBFlow一样的ORM的优势在哪里呢?
值得一提的是Realm 的维护者已经 意识到了这些限制 ,而且在一定程度上,许多问题都可能被解决(见这里 和 这里))。Realm也的确具有一些其它的优势,比如性能以及在iOS和安卓之间共享数据的能力。
分享到:
相关推荐
在不再需要 Realm 实例时,记得关闭它以释放资源: ```java realm.close(); ``` ### 9. 使用 RealmResults 和 RealmList `RealmResults` 是一个可观察的列表,当 Realm 中的数据发生变化时,它会自动更新。`...
8. **关闭 Realm**:在不再使用 Realm 实例时,记得调用 `close()` 方法释放资源。 在《MyApplication》这个项目中,开发者可能已经将Realm数据库应用到了各种场景,如用户登录信息存储、应用设置保存、消息缓存等...
Realm是一款流行的开源数据库解决方案,专为移动应用设计,特别是在Android平台上。 Realm-0.86.1 版本是针对Eclipse集成开发环境的一个特定版本,对于那些仍然使用Eclipse而不是Android Studio的开发者来说,这是一...
Realm-JSON, 使用领域和JSON的简洁的地幔 Realm JSON 一种简洁的地幔使用领域和JSON的方法...更改方法 - deepCopy 替换了 - shallowCopy 以前的功能,它不再维护对象键的一个主更新为使用领域 0.85.0中的原生主键支持更
Realm 支持MVVM(Model-View-ViewModel)架构,这是一种在Xamarin.Forms中广泛使用的模式,有助于提高代码的可维护性和可测试性。 1. **Xamarin.Forms 基础** Xamarin.Forms 提供了一套统一的 API,可以在多个...
:warning: 不推荐使用该存储库不再维护。 请按照上的教程进行操作请参阅以下特定客户回购协议: 等等。 原始自述文件在下面继续。任务跟踪器教程任务跟踪器是一个协作项目管理工具。应用说明移动应用程序(Swift / ...
注意:该项目已终止,不再由Tresorit维护或支持。 该存储库仅用于存档目的。ZeroKit-Realm-Auth-Provider ZeroKit-Realm-auth-provider是Realm Object Server(ROS)的身份验证模块,用于启用基于ZeroKit的身份验证...
虽然 Rx-Realm 不再是必需的,但理解其背后的反应式编程思想对于使用 Realm 或其他类似库(如 Room with RxJava)进行数据库操作是非常有益的。反应式编程允许开发者以声明式的方式编写代码,减少回调地狱,提高代码...
Realm 是一种现代的、对象关系映射(ORM)工具,专为移动应用设计,支持 Swift 和其他语言。它提供了便捷的方式来存储和检索数据,同时保持性能和内存效率。 ### 1. RealmCache 的工作原理 RealmCache 在 Realm ...
总的来说, Realm 为 iOS 开发提供了一种强大而易于使用的数据持久化解决方案,尤其适合 Swift 开发者,其简洁的 API 和对象映射方式极大地简化了数据库操作。通过实践和理解 Realm,开发者可以构建出更加高效、可靠...
领域任务(已弃用) 该项目已弃用,不再有效维护。 一个基本的任务管理应用程序...1.获取领域对象服务器Realm Tasks应用程序使用Realm对象服务器在它们之间同步任务。 访问Realm对象服务器的最快方法是注册免费的Realm
标题中的“MultiRealm”是一个专为Ruby开发的框架,旨在简化在后台处理多个Realm(数据库实例)的操作。 Realm通常指的是数据库或数据存储区域,尤其在移动应用开发中,如 Realm.io,它是一个流行的对象关系映射...
该插件增加了对使用realm:方案URI的ES导入说明符的支持,以允许导入对当前领域内的全局值进行重复数据删除的固定引用。 变化 2.0.0: Meta:不再在dist中生成CJS入口点 Meta:现在导出esbuild()适配器函数 错误...
安装Realm Royale高清壁纸New Tab主题,并享受Realm Royale世界,皮肤,故事模式等的高清壁纸。 爱情王国皇家吗? 安装Realm Royale HD Wallpapers New Tab Theme,并享受Realm Royale Story模式,游戏玩法,皮肤,...
Monarch 是一个专门为 Realm 迁移提供便利的 Java 库,它的主要目标是简化数据库版本管理,尤其是在数据模型发生变化时的迁移过程。 Realm 是一款流行的对象关系映射(ORM)框架,广泛应用于 Android 开发中,它允许...
内存泄漏是指程序中已不再使用的对象由于某些原因仍然被引用,导致垃圾回收器无法正确回收这些对象,从而占用宝贵的内存资源。Pierre-Yves Ricau 用非技术性的例子解释了这个问题:想象你的手代表应用可用的内存,而...
Shiro的会话管理允许开发者在不同的应用架构层使用一致的会话API,不再受限于特定的容器,如Servlet或EJB容器。 CacheManager负责为Shiro的其他组件提供缓存支持,这可以提高认证和授权等操作的效率。 Shiro的认证...
为什么是 RealmEasy? 我创建 RealmEasy 来解决两个问题。 从 Realm 0.87 开始,不再可能将默认 Realm 设置为 inMemoryRealm。 这意味着您必须要么使用真正的 default.realm 进行单元测试,要么在整个代码中传递该...
注意:该项目已终止,不再由Tresorit维护或支持。 该存储库仅用于存档目的。 ZeroKit Node示例后端 这是一个使用应用程序开发自己的ZeroKit的后端服务时可以参考的示例。 它提供了一个功能齐全的REST api,供我们...
因此,我们不再维护此样本领域存储库。 如果您希望查看示例领域,则可以看到一个有效的,维护的 博客文章还提供了一个示例,该示例在Elasticsearch 6.3或更高版本中实现自定义领域,并提供了一些帮助。 Elastic...