-
Notifications
You must be signed in to change notification settings - Fork 588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Observable.create()
to construct LocationServicesOkObservable
#438
Use Observable.create()
to construct LocationServicesOkObservable
#438
Conversation
public void cancel() throws Exception { | ||
try { | ||
context.unregisterReceiver(broadcastReceiver); | ||
} catch (IllegalStateException ignored) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may end up leaking a context if this will get called before the subscribe
finishes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch @dariuszseweryn 👍 There may be a case like that. For example, considering the following execution flow:
- The program passes by line 51 at
if (!emitter.isDisposed()) {
. There's still at least a subscriber of thisObservable
, so thecontext.registerReceiver()
is about to be executed. - Then, somehow no subscriber subscribes to the
Observable
anymore. The code insetCancellable()
gets invoked. - Then
context.registerReceiver()
gets executed. Thus the leak has just happened.
I'm thinking about doing another check if (!emitter.isDisposed())
right after context.registerReceiver()
but it looks kinda weird. I never wrote such conditional flow before. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or another idea is to move the setCancellable()
into the isDispose()
check. For example:
if (!emitter.isDisposed()) {
context.registerReceiver(broadcastReceiver, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
emitter.onNext(initialValue);
emitter.setCancellable(new Cancellable() {
@Override
public void cancel() throws Exception {
try {
context.unregisterReceiver(broadcastReceiver);
} catch (IllegalStateException ignored) {
}
}
});
}
Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed the impl into below based on @akarnokd's suggestion link:
public Observable<Boolean> get() {
return Observable.create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(final ObservableEmitter<Boolean> emitter) throws Exception {
final boolean initialValue = locationServicesStatus.isLocationProviderOk();
final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final boolean newValue = locationServicesStatus.isLocationProviderOk();
emitter.onNext(newValue);
}
};
emitter.onNext(initialValue);
context.registerReceiver(broadcastReceiver, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
emitter.setCancellable(new Cancellable() {
@Override
public void cancel() throws Exception {
try {
context.unregisterReceiver(broadcastReceiver);
} catch (IllegalStateException ignored) {
}
}
});
}
}).distinctUntilChanged();
}
I think this impl is able to prevent the above leak from happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, but we should get rid of the try/catch
in the Cancellable
as it could only hide potential issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dariuszseweryn Good call 👍 Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me :) #notasubclassingfananyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
Awesome! Thank you for the contribution. |
Fix #404 again.