Q1:请告诉我以下两种implementation
方式之间的区别(关于get realm instance
)。我想知道哪一个更快,内存更轻,推荐什么?
1。设置并获取领域为默认值(使用特定配置)
private void setupCustomRealm() {
if (!Utils.isStringHasText(databaseName)) {
databaseName = DbManager.getInstance().getCurrentDb();
}
// get config
RealmConfiguration config = getRealmConfigByDBName(databaseName);
Realm.setDefaultConfiguration(config);
Realm.compactRealm(config);
}
public Realm getCustomRealm() {
if (firstTime) {
setupCustomRealm();
}
return Realm.getDefaultInstance();
}
2.直接从配置获取领域
public Realm getCustomRealm(Context context) {
if (!Utils.isStringHasText(databaseName)) {
databaseName = DbManager.getInstance().getCurrentDb();
}
// get config
RealmConfiguration config = getRealmConfigByDBName(context, databaseName);
Realm.compactRealm(config);
return Realm.getInstance(config);
}
Q2:在我的应用程序中,现在我们考虑两种实现方式。
1:每当我们需要使用Database(在工作线程和UI线程中)执行某些操作时,我们都会创建一个新的Realm实例,并在任务完成时关闭它。
2:我们只创建一个Realm实例并让它与应用程序一起生存,当退出应用程序时我们关闭上面的实例。
请解释一下每个方法的优缺点以及推荐的方法(我的应用程序使用Service处理数据库和网络连接)
如果我有2个繁重的任务(需要很长时间来完成它的事务),执行2任务由一个Realm实例和在2个独立线程中的2个Realm实例上执行2任务有什么区别(我的意思是一个线程有一个Realm实例和实例将执行上面两个任务中的一个),哪个更安全,更快。
如果在执行事务时出现问题(例如没有响应或抛出某些异常),将会发生什么?
答案 0 :(得分:4)
注意:我不是官方的Realm人员,但我现在已经使用Realm了一段时间。
1。)值得注意的是:
RealmConfiguration
访问给定的Realm文件,因此这里的 第一个 解决方案更可取(不要创建每个领域的新配置。)Realm.compactRealm(RealmConfig)
仅在任何线程上没有打开的Realm实例时有效。因此,无论是在应用程序启动时,还是在应用程序完成时(我个人发现它使启动速度变慢,因此当我的活动计数达到compactRealm()
时我会调用0
,我使用保留的片段来管理Realm.getInstance()
活动 - 但那只是我)。 2。)值得注意的是,0
在第一次调用时会创建一个线程本地缓存(缓存在属于同一个线程的Realm实例之间共享,并递增计数器以指示Realm实例的数量是多少在该给定线程上打开。当该计数器在所有实例上调用realm.close()
后达到Realm
时,缓存将被清除。
值得注意的是Realm
实例是线程限制的,因此您需要在使用它的任何线程上打开一个新的realm.close()
。这意味着如果您在IntentService中使用它,则需要打开一个新的Realm(因为它位于后台线程中)。
在后台线程上打开的Realm实例上调用Realm realm = null;
try {
realm = Realm.getDefaultInstance();
//do database operations
} finally {
if(realm != null) {
realm.close();
}
}
非常重要。
try(Realm realm = Realm.getDefaultInstance()) {
//do database operations
}
或API 19 +:
realm.close()
当您在特定Realm实例上调用open/close
时,它会使属于它的结果和对象无效。因此,对onCreate()
和onDestroy()
中的RealmConfiguration realmConfig = new RealmConfiguration.Builder(appContext).build()
领域都有意义,或者在应用程序中打开它并在UI线程上共享相同的UI线程Realm实例。
(关闭UI线程上的Realm实例并不重要,除非您打算在所有这些实例关闭后压缩它,但必须关闭后台线程上的Realm实例。)
注意:如果您在Application.onCreate()
中调用getFilesDir()
,则在某些设备上调用null
会失败,因为RealmConfiguration
可以返回executeTransactionAsync()
,所以它是最好在第一个活动开始后初始化RealmAsyncTask
。
考虑到所有这些,2)的答案是:
虽然我个人为UI线程创建了一个Realm实例,但您仍然需要为任何后台线程打开(并关闭!)一个新的Realm实例。
我使用Realm的单个实例作为UI线程,因为它更容易注入这种方式,并且因为RealmResults<T>
的{{1}}在基础Realm实例关闭的同时被取消它仍然在执行,所以我真的不希望这种情况发生。 :)
不要忘记,您需要UI线程上的Realm实例才能从领域查询中显示copyFromRealm()
(除非您打算使用IntentService
,这会使一切都使用更多内存,并且通常较慢)
realm.cancelTransaction()
的工作方式与普通的后台线程类似,因此您也应该关闭那里的realm实例。
无论是同一个Realm实例还是另一个(只确保你在该给定线程上有一个Realm实例),这两个繁重的任务都可以工作,但我建议一个接一个地连续执行这些任务。
如果在交易期间有异常,您应该调用realm.executeTransaction(new Realm.Transaction() { ... });
(文档说明开始/提交,但它总是忘记取消)。
如果您不想手动管理开始/提交/取消,则应使用executeTransaction()
,因为它会自动为您调用begin / commit / cancel。我个人在任何地方使用docker-php-ext-install ftp
因为它很方便。