- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
Realm.getInstance(context)
很少会返回一个已经关闭的 Realm 实例。这怎么可能?
根据 https://realm.io/news/using-realm-with-rxjava/,我将 Realm 与 RxJava 结合使用
特别是,此方法抛出一个 IllegalStateException: This Realm instance has already been closed, making it unusable.
@Override
public void call(final Subscriber<? super RealmList<T>> subscriber) {
final Realm realm = Realm.getInstance(context);
subscriber.add(Subscriptions.create(new Action0() {
@Override
public void call() {
try {
realm.close();
} catch (RealmException ex) {
subscriber.onError(ex);
}
}
}));
RealmList<T> object;
realm.beginTransaction(); //THROWS EXCEPTION
//...
}
如果我注释掉 realm.close();
问题,没问题。不过我认为这会导致 native 内存泄漏。
关于为什么会发生这种情况,我最好的猜测是对该方法进行了多次调用,如果这些方法调用完全一致,那么可以检索已经关闭的 Realm 实例?
编辑:通过使用 Schedulers.io()
,我收到了很多 Calling close() on a Realm that already closed
警告。我的猜测是,在我使用完 .io()
线程后,不知何故, Realm 实例会自动关闭。虽然不确定为什么会发生这种情况。
EDIT2:通过切换到对我的可观察对象使用 Schedulers.newThread()
而不是 Schedulers.io()
,问题不再出现。但是我看到很多 Remember to call close() on all Realm instances
警告。我很确定我要关闭它们,所以我对此很困惑。
EDIT3:通过切换到使用 AndroidSchedulers.mainThread()
,没有错误。除了我的 Realm 调用在主线程上运行,这很糟糕。我猜为什么这不会导致警告是因为 realm
现在位于主线程上,这也是调用 realm.close()
的地方(通过 rx .subscriber
).
EDIT4:这是我的 Realm 可观察调用的逻辑。
@Override
public Observable<List<ImageArticleCategoryEntity>> getArticleBuckets() {
return RealmObservable.list(context, GET_ARTICLE_BUCKETS)
.filter(FILTER_OUT_NULL_OR_EMPTY_LIST)
.switchIfEmpty(refreshAndSaveAndLoadNewDataFromDb)
.map(CONVERT_FROM_REALMLIST_TO_IMAGE_ARTICLE_ENTITYLIST);
}
public void loadArticleImages() {
articleRepo.getArticleBuckets()
.subscribeOn(RealmThread.get())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<ImageArticleCategoryEntity>>() {
@Override
public void onCompleted() {
Timber.v("Loading article images complete!");
if (view != null)
view.hideLoadingAnimation();
}
@Override
public void onError(Throwable e) {
Timber.e("Error loading article images", e);
Log.e("tag", "Error loading article images", e);
if (view != null) {
view.hideLoadingAnimation();
view.showLoadingErrorToast();
}
}
@Override
public void onNext(List<ImageArticleCategoryEntity> integerImageArticleCategoryEntityHashMap) {
if (view != null)
view.loadArticleImages(integerImageArticleCategoryEntityHashMap);
}
});
最佳答案
让我们简化 Realm
的生命周期实例被管理。如果我们在 Activity
的恢复/暂停周期的上下文中管理它或 Fragment
,我们可以更轻松地控制和停止可能消耗 Realm
的工作实例。 RxAndroid 中的工具对此有很大帮助。
所以,对于这个例子,我假设这是从 Activity
发生的, 但可以从 Fragment
使用非常相似的方法,或者提取到辅助类中,只需一点点管道。
如果您绑定(bind)您的 Observable
到 Activity
的生命周期或 Fragment
使用 RxAndroid,您似乎已经在使用它来处理 mainThread()
,您应该能够管理您的 Realm
在生命周期内轻松实例化。我也在使用 RxAsyncUtil对于 Async.toAsync
, 这使得 Realm
的原创实例更简单。
我使用 Rx 的次数比使用 Realm 的次数多得多(尽管我对它玩得很开心),所以如果我的某些 API 使用不完美,请原谅我。为了便于编写和阅读,我还将一些东西缩写为 java8 风格的 lambda。如果您不使用像 retrolambda 这样的东西,那么将它转换回来应该仍然很容易。
class MyActivity extends Activity {
private final CompositeSubscriptions realmSubscriptions = new CompositeSubscription();
private AsyncSubject<Realm> realm;
@Override
protected void onResume() {
super.onResume();
realm = AsyncSubject.create();
realmSubscriptions.add(getRealmInstance());
// This could actually happen anytime between onResume and onPause.
realmSubscriptions.add(loadArticlesImages());
}
private <T> Observable<T> bindToRealm(final Observable<T> observable) {
// Utility to bind to the activity lifecycle, observe on the main thread
// (implicit in the bindActivity call), and do work on the Realm thread.
return AppObservable.bindActivity(this, observable.subscribeOn(RealmThread.get()));
}
private Observable<List<ImageArticleCategoryEntity>> getArticleBuckets(
final Realm realm) {
/* As is, except the realm instance should be passed to RealmObservable.list instead
of the context. */
}
private Subscription getRealmInstance() {
// Grab the realm instance on the realm thread, while caching it in our AsyncSubject.
return bindtoRealm(Async.toAsync(() -> Realm.getInstance(MyActivity.this)))
.subscribe(realm);
}
private Subscription loadArticleImages() {
// Using the flatMap lets us defer this execution until the
// Realm instance comes back from being created on the Realm thread.
// Since it is in an AsyncSubject, it will be available nearly
// immediately once it has been created, and is cached for any future
// subscribers.
return bindToRealm(realm.flatMap((realm) ->
articleRepo.getArticleBuckets(realm).subscribeOn(RealmThread.get())))
.subscribe(
(next) -> {
if (view != null) {
view.loadArticleImages(next);
}
},
(error) -> {
Timber.e("Error loading article images", e);
Log.e("tag", "Error loading article images", e);
if (view != null) {
view.hideLoadingAnimation();
view.showLoadingErrorToast();
}
},
// onCompleted
() -> {
Timber.v("Loading article images complete!");
if (view != null) view.hideLoadingAnimation();
});
}
@Override
protected void onPause() {
// Stop any work which we added that involves the Realm instance.
realmSubscriptions.clear();
// Clean up the AsyncObservable. If it has a Realm instance, close it.
if (realm.getValue() != null) {
realm.getValue().close();
}
realm.dispose();
realm = null;
super.onPause();
}
}
您应该能够根据需要轻松地将其提取到 Activity 之外,并且只需为生命周期绑定(bind)传递一个 Activity/Fragment 实例,以及 Observable<Realm>
在这种情况下将是 AsyncSubject
.如果由于订阅工作仍然存在竞争条件,您可能需要尝试添加 .unsubscribeOn(AndroidSchedulers.mainThread())
甚至 .unsubscribeOn(Schedulers.immediate())
(我实际上不确定在这种情况下哪个最好)到 bindToRealm
以确保取消订阅在您想要的时候发生在 onPause
中, 在 Realm
之前实例已关闭。
关于Android:Realm.getInstance(context) 返回一个已经关闭的 Realm 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30629355/
我正在按照本教程创建 Singleton,所有者在以下方法时有评论 http://www.journaldev.com/1377/java-singleton-design-pattern-best-
package com.example.vivanksharma.firebase; import android.support.v7.app.AppCompatActivity; import a
自从首次引入它来替换 Date 以来,我一直在使用静态方法 Calendar.getInstance() 来获取新的 Calendar目的。我从来没有遇到过问题,但出于某种原因我只是想知道使用 Gre
我正在使用适用于 Windows 8 的 MVVM Light 第 4 版;它包括 SimpleIOC。在各种示例中,我有时会看到基于 SimpleIoc 请求对象的代码......有时它基于 Ser
我看过这个post关于注册泛型类型。 如何注册的示例: bind(new TypeLiteral>() {}).to((Class>) ResponseDal.class); 但是如何从注入(inj
我想在我的 unitTest 中从 Guice injector 注入(inject)一个实例。 我可以使用哪个微分器? 我知道构造函数参数中使用了@annotation机制 但是 junit 不允许
我正在使用静态实例对象来获取与应用程序中另一个 Activity 相关的数据。但这会导致内存泄漏。 public class ChartActivity extends AppCompatActivi
以前用过C#,我考虑过 Calendar cal = Calendar.getInstance(); 根据 GoF 成为单例方法 Singleton pattern (Wikipedia)我想知道如何
我很难找到以对性能最友好的方式使用单例类的正确方法。我有 3 种方法,也许有人可以向我解释最有效的方法: 1: public functionA() { SingletonClassA.get
最近我阅读了一些使用广泛遵循 getInstance() 方法的 C++ 代码: class S { private: int some_int = 0; public
许多公开可用的 Java API 似乎都使用 getInstance 来生成和返回对象。我很好奇为什么会这样——为什么不直接使用默认/参数化构造函数呢? 是否有关联的设计模式? 最佳答案 我建议阅读
我遇到过单例模式。我无法理解 singletonobj.getinstance().dosomething() //1st one 和 singletonobj.dosomething() //2nd
getInstance() 在 Java 中的作用是什么? 在我的研究过程中,我一直在读到 getInstance() 有助于实现单例设计模式(据我了解,这意味着整个程序中只有一个实例)。但是我不能只
Firebase Firestore 提供 getInstance()方法,它打开一个套接字(在应用程序执行的任何时候只有一个)并实例化 Firestore 客户端。 我想查询和存储数据,使用或不使用
我正在将一个表单组件放入 joomla.In 中,我将在其中放置一个文本框、一个编辑器和一个按钮。 我为此表单创建了 View 文件,并且组件已成功安装。但是当我单击以在前端显示此表单时,会出现如下错
我正在尝试跟踪人们是否从广告或其他地方找到了我的 Android 应用。所以我发现谷歌分析可以通过这个表单生成的精心构建的 url 来跟踪它: http://code.google.com/mobil
我观看了此视频(https://www.youtube.com/watch?v=idb6hOxlyb8),该视频是2013年8月上传的。它声称我们应该使用 ptor.get(url) 而不是 brow
创建 google-service.json 后运行示例时,应用在尝试在 SignInActivity 中获取数据库引用时崩溃 mDatabase = FirebaseDatabase.getInst
基于以下问题:Decimal point or decimal comma in Android我尝试获取设备中使用的小数点分隔符。我正在使用Kotlin,因此我的代码如下所示: import and
从 Fabric Crashlytics 迁移到 FirebaseCrashlytics SDK 后,我在另一个进程(不是主进程)上遇到了一些崩溃。 当在 Activity 中调用 FirebaseC
我是一名优秀的程序员,十分优秀!