我在我的Android应用程序中使用RxJava,并且多次遇到OutOfMemoryError。我用设备管理器检查了它,我刚注意到,我有超过200个线程,大多数处于等待状态,通常是RxCachedThreadSchedulers。 OOMError因为有太多线程而被提出。 我还注意到,如果我按下一个按钮,它调用一个服务并获取一个令牌并缓存它,那么线程数会增加5倍!
所以,我用Google搜索并发现,Schedulers.io可以创建无限的线程。当我用Schedulers.computation替换每个Schedulers.io时,问题就消失了,但这没有任何意义,因为我使用Schedulers.io就像它应该被使用一样。
那么我如何使用Schedulers.io并确保它不会创建太多线程?
更新
我这样取消订阅:
final Scheduler.Worker worker = Schedulers.io().createWorker();
worker.schedule(new Action0() {
@Override
public void call() {
long last = lastServerCommunication.getMillis();
LongPreference pref = new LongPreference(mSharedPreferences, PREF_KEY_LAST_SERVER_COMMUNICATION);
pref.set(last);
worker.unsubscribe();
}
});
更新#2
我使用Schedulers.io的常规方式是:
public Observable<Scenario> load() {
return Observable
.create(new Observable.OnSubscribe<Scenario>() {
@Override
public void call(Subscriber<? super Scenario> subscriber) {
try {
Scenario scenario = mGson.fromJson(mSharedPreferences.getString("SCENARIO", null), Scenario.class);
subscriber.onNext(scenario);
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(new Throwable());
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
和
mSomeSubscription = mSomeManager.readFromDatabase()
.subscribeOn(Schedulers.io())
.subscribe(new Observer<List<SomeEntry>>() {
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) {
// some logging
}
@Override
public void onNext(List<SomeEntry> Entries) {
// Some action
}
});
答案 0 :(得分:3)
好的,我找到了原因。请参阅说明更新#2 :
return Observable.create(new Observable.OnSubscribe<Something>() {
@Override
public void call(Subscriber<? super Something> subscriber) {
try {
// Some action
subscriber.onNext(scenario);
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(new Throwable());
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
当你创建像这样的冷Observable序列时,你必须确保你在订阅者上调用onCompleted,参见上面的subscriber.onCompleted();
。
好吧,代码中的某些地方并没有,所以生成了线程。
非常感谢 akarnokd 寻求帮助!
答案 1 :(得分:2)
如果您使用Schedulers.io().createWorker()
,一旦完成,您必须unsubscribe()
Worker
。常规的RxJava操作符不应泄漏任何工作者,因此也不应泄漏线程。
答案 2 :(得分:1)
太棒了,如果你不调用onComplete方法,那么线程(由Schedulers.io()
创建)将保持等待并存在于那些冷可观察对象。