I'm playing with rxjava and found there is a risk of memory leak if a subscription is not completed before an activity is destroyed because "observables retain a reference to the context". One of the demos for such case is given as below, if the subscription is not unsubscribed onDestroyed (source: https://github.com/dlew/android-subscription-leaks/blob/master/app/src/main/java/net/danlew/rxsubscriptions/LeakingActivity.java):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaking);
// This is a hot Observable that never ends;
// thus LeakingActivity can never be reclaimed
mSubscription = Observable.interval(1, TimeUnit.SECONDS)
.subscribe(new Action1<Long>() {
#Override public void call(Long aLong) {
Timber.d("LeakingActivity received: " + aLong);
}
});
}
However I'm not sure why such a leak exists. I've checked the Observable class and seen nothing relevant to Context. So all I can think of is because there is an anonymous Action1 class defined within the subscribe method which hold a reference to the activity instance. And the observable in turn holds a reference to the action. Am I right?
Thanks
The .subscribe(new Action1<Long>() { }) creates and stores nested class which as any non-static nested class has reference to containg class instance - in this case the Activity.
To resolve that you can Subscription.unsubscribe the mSubscription in the Activity.onDestroy
Related
I'm new to RxJava and I need to integrate it into an existing project. I need to refactor the existing code, adding Observables for networking (Socket IO).
Currently when a network request is made (client -> server) a callback (interface) is added to a HashMap and once the request is completed, it will deliver the data back to the caller:
// Singleton
public class API {
public void checkTicket(String ticketId, final String networkRequestId, Callback callback) {
// Add the callback to the hashmap
registerCallback(networkRequestId, callback);
JSONObject json = RequestFactory.createTicketCheckerRequest(ticketId);
// Make the network request
getSocket().checkTicket(json, new Callback() {
#Override
public void onRequestDone(Response response) {
// Retrieve the callback
callback = getCallback(networkRequestId);
// Don't keep reference, remove from hashmap
unsubscribeCallback(networkRequestId);
// Check if it's unsuccessful and build the corresponding error response
if (!response.isSuccess()) {
// build custom error response
response = ResponseFactory.buildError(response);
}
// Deliver response from server
callback.onRequestDone(response);
}
});
}
}
It can be called from Activities and Fragments:
private void checkTicket() {
String ticketId = editText.getText().toString();
API.getInstance().checkTicket(ticketId, REQUEST_ID_CHECK_TICKET, new Callback() {
#Override
protected void onRequestDone(Response response) {
textView.setText(response.getData());
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
// Removes callback from HashMap in case of the UI is destroyed before the arrives
API.getInstance().unsubscribe(REQUEST_ID_CHECK_TICKET);
}
The above code works but it's really tight with the UI's lifecycle and sometimes it's causing memory leak, because onDestroy() is not getting called (if you navigate between activities and Android OS kills the "paused" activities from the stack) or because the anonymous inner classes (callbacks) which are holding a reference to the UI, and from now on I need to support orientation change.
This is the code that I have implemented using RxJava:
API:
public Observable<Response> checkTicket(String ticketId) {
return Observable.create(subscriber -> {
JSONObject json = RequestFactory.createTicketCheckerRequest(ticketId);
// Make the network request
getSocket().checkTicket(json, new Callback() {
#Override
public void onRequestDone(Response response) {
subscriber.onNext(response);
subscriber.onComplete();
}
});
});
}
This is how it's called from the UI:
private CompositeDisposable mDisposables = new CompositeDisposable();
private void checkTicket() {
//////
Disposable disposable = API.getInstance().checkTicket(ticketId)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(result -> {
textView.setText(result.getData());
});
mDisposables.add(disposable);
}
#Override
public void onStop() {
super.onStop();
if (!mDisposables.isDisposed()) {
mDisposables.dispose();
}
}
The above RxJava is working, however if an orientation change occurs the data is not returned because the Observer is unsubscribed.
Is the above implementation correct?
How should I subscribe without executing the request? Subscribe and wait for data change.
Another alternative would be EventBus but this is just Plan B. EventBus fits exactly my requirements, subscribe and wait for data change, but I want to evict boilerplate.
I have read other articles by using Fragment's setRetainInstance(true) but what if I need to use it from an Activity? What if I don't want to retain the state of the Fragment?
People suggested to use MVVM or MVP architecture, but I don't have the time to refactor the entire project.
I will suggest you move to MVVM. With your presented code, it is not that hard. Here is a sample code of how it will look like
Your ModelView
public class MyViewModel extends ViewModel {
private CompositeDisposable mDisposables = new CompositeDisposable();
private MutableLiveData<Response> response;
public LiveData<Response> getResponse() {
if (response == null) {
response = new MutableLiveData<Response>();
loadData();
}
return response;
}
private void loadData() {
Disposable disposable = API.getInstance().checkTicket(ticketId)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(result -> {
response.postValue(result.getData());
});
mDisposables.add(disposable);
}
void onCleared()
{
super.onCleared();
mDisposables.clear(); //no more leaks. It takes care of lifecycle for you
}
}
Your Activity
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getResponse().observe(this, response -> {
// update UI
textView.setText(response); //response = Response object from Live data
});
}
}
If you don't want to handle configuration changes and want to cache data from observables, you can use BehaviorSubjects and a hot observable. This will allow you to get the most recent item that the observable published.
Other than that, I suggest you use the ViewModel from the architecture components. It will allow you to create a component that is bound to the activity but will not be affected by the lifecycle (except termination, obviously). Surprisingly enough, ViewModelProviders are implemented as fragments with setRetainInstance(true). You don't have to completely refactor the entire app. Just move the ones that you want to preserve during configuration changes.
You need to consider the logical scope of your network requests, and this is entirely separate from whether you're using RxJava. Background tasks like network requests need to be owned by an Android component (Application, Activity, etc.) with the appropriate lifetime. The usual way to make activity-scoped background tasks survive a config change is to host them in a retained fragment. You would still do that if you were using RxJava.
Android OS kills the "paused" activities from the stack
This doesn't happen unless something has changed in Android 8 or newer. The documentation suggests that the framework could destroy individual activities in the backstack, but currently it only destroys the entire task when it's in the background. Your app is correct and future-proof if and only if it works with the "don't keep activities" developer option on.
The suggested way to implement ViewModel is to expose the changing data by using LiveData objects to activities, fragments and views. There are cases, when LiveData is not an ideal answer or no answer at all.
The natural alternative would be, to apply the observer pattern to the ViewModel, make it an observable. When registering observers to the ViewModel, the ViewModel will hold callback references to notify the observers.
The documentation says, a ViewModel must not hold references to activities, fragments or views. The only answer to the question "why" I found is, that this may cause memory leaks. Then how about cleaning up the references to avoid memory leaks?
For views this is a difficulty. There is no defined moment, when the view goes away. But activities and fragments have a defined lifecycle. So there are places to unregister as observers.
What do you think? Is it valid to register activities as observers to ViewModels if you take care to always unregister them? Did you hit upon any valid information about this question?
I set a small reward for the best answer. It's not because I think it a recommended solution (as it does not work with views). I just want to know and extend my options.
public class ExampleViewModel extends ViewModel {
public interface OnEndListener {
public void onEnd();
}
private List<OnEndListener> onEndListeners = new ArrayList<>();
public void setOnEndListener(OnEndListener onEndListener) {
onEndListeners.add(onEndListener);
}
public void removeOnEndListener(OnEndListener onEndListener) {
onEndListeners.remove(onEndListener);
}
public void somethingHappens() {
for (OnEndListener onEndListener: new ArrayList<OnEndListener>(onEndListeners) ) {
onEndListener.onEnd();
}
}
}
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
ExampleViewModel.OnEndListener onEndListener;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onEndListener = new ExampleViewModel.OnEndListener() {
#Override
public void onEnd() {
finish();
}
};
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.setOnEndListener(onEndListener);
}
#Override
protected void onDestroy() {
super.onDestroy();
exampleViewModel.removeOnEndListener(onEndListener);
}
}
To ask "am I allowed..." is not really a useful question, IMO. The docs are clear that what you are suggesting is discouraged and why. That said, I expect that your code would probably work as expected and is therefore "allowed" (i.e. not prevented by a technical constraint).
One possible gotcha scenario: InstanceA of ExampleActivity is started and kicks off some long-running task on the ExampleViewModel. Then, before the task completes, the device is rotated and InstanceA is destroyed because of the configuration change. Then, in between the time when InstanceA is destroyed and a new InstanceB is created, the long-running task completes and your view model calls onEndListener.onEnd(). Except: Oh no! The onEndListener is null because it was cleared when InstanceA was destroyed and hasn't yet been set by InstanceB: NullPointerException
ViewModel was designed (in part) precisely to handle edge cases like the gotcha scenario above. So instead of working against the intended use of the ViewModel, why not just use the tools it offers along with LiveData to accomplish the same thing? (And with less code, I might add.)
public class ExampleActivity extends AppCompatActivity {
ExampleViewModel exampleViewModel;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
exampleViewModel = ViewModelProviders.of(this).get(ExampleViewModel.class);
exampleViewModel.getOnEndLive().observe(this, new Observer<Boolean>() {
#Override
public void onChanged(#Nullable Boolean onEnd) {
if (onEnd != null && onEnd) {
finish();
}
}
});
}
}
public class ExampleViewModel extends ViewModel {
private MutableLiveData<Boolean> onEndLive = new MutableLiveData<>();
public MutableLiveData<Boolean> getOnEndLive() {
return onEndLive;
}
public void somethingHappens() {
onEndLive.setValue(true);
}
}
Think of the LiveData in this case not as actual "data" per se, but as a signal that you can pass from your ViewModel to your Activity. I use this pattern all the time.
I working on android project with clean architecture.
I have the below class:
public abstract class RxBaseInteractor<T, Params> {
private final CompositeDisposable disposables;
public RxBaseInteractor() {
this.disposables = new CompositeDisposable();
}
abstract public Observable<T> buildUseCaseObservable(Params params);
public void execute(DisposableObserver<T> observer, Params params) {
Preconditions.checkNotNull(observer);
final Observable<T> observable = this.buildUseCaseObservable(params)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
addDisposable(observable.subscribeWith(observer));
}
public void dispose() {
if (!disposables.isDisposed()) {
disposables.dispose();
}
}
protected void addDisposable(Disposable disposable) {
Preconditions.checkNotNull(disposable);
Preconditions.checkNotNull(disposables);
disposables.add(disposable);
}
}
So execute(..) take a DisposableObserver and then there is a dispose() method which is called to dispose this observable.
In my case the observable may come from WebApi using retrofit or cache using Realm.
Now in the presenter onDestroy(), i called the interactor.dispose() like:
#Override public void destroy() {
super.destroy();
myInteractor.dispose();
}
which is called after that from the view:
#Override public void onDestroy() {
super.onDestroy();
if (getPresenter() != null) {
getPresenter().destroy();
}
}
I fully understanding the architecture and also i understand disposing un-managed network or database resources but i need to fully understand if in this case the dispose of observable really matter as i thought that Retrofit or Realm auto manage closing a connections and disposing there resources.
I think it's not related to dispose realm or retrofit resources but it may be related to unsubscribe on the observable it self as i checked the documentation and i found :
Class DisposableObserver: An abstract Observer that allows asynchronous cancellation by
implementing Disposable. All pre-implemented final methods are
thread-safe.
Use the public dispose() method to dispose the sequence from within an
onNext implementation.
But i still not understand the benefits of using it. Is it for unsubscribe from the observable when destroying the view so it will go from onNext() to onComplete() and close the subscription on the emitter?
The reason behind using dispose method is because after the system initiate the view (activity or fragment), the subscription gets start and then you have decided to go back or initiate another view while the older subscription is still getting executed and didn't finish its job. This means that it's still in the memory which will cause a memory leak. So you have to call dispose method for unsubscribe.
Adding more to #abozaid's answer, When older subscription is still On and in the meantime, our user switches to other view (activity or fragment) or closes older view (or application itself), it'll definitely leak memory.
But, if we were observing observable for UI updation with AndroidSchedulers.mainThread() scheduler, then our code would crash because at the time of updating UI, the view and context would have gone away (or destroyed).
myObservable.observeOn(AndroidSchedulers.mainThread()) // like this
One other point, I can add here is that, even if we handle the crash by putting precaution in code, the subscription running unused would hamper performance at some stage.
New to RxJava and I have question about interface callbacks ( called from inner layer/module of code through interface variable) vs RxJava.
To make it more clear, quick example:
Standard callback interface implementation, interface, class A and B
interface CustomCallback {
void onCallbackCalled(String str);
}
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB(new CustomCallback() {
#Override
public void onCallbackCalled(String str) {
System.out.println("Callback called " + str);
}
});
}
}
class ClassB {
private CustomCallback customCallback;
public ClassB(CustomCallback callback) {
customCallback = callback;
}
private void somethingHappened() {
customCallback.onCallbackCalled("method somethingHappened");
}
}
When classB method "somethingHappened" is called, result is: "Callback called method somethingHappened".
Interface's method onCallbackCalled(String str) can be called from classB as many times as I want.
CLASS A ↓ ............................................ injection of interface through constructor
CLASS B................↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ onCallbackCalled(...) 0...n number
Now RxJava. 99% of cases which I find.
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private Observable<String> getObservable() {
return Observable.just(can be different from "just", for sake of example);
}
}
Scheme is:
CLASS A ↓........................ one call for getting Observable resource
CLASS B................↑ EDIT returns observable which emits 0...n values
So basically you call from top layer ( in this example) and you get response about state from inner layer.
QUESTIONS:
1) What in case when you have a model ( inner layer) which is changing dynamically ( but not any kind of AsyncTask etc.), and you want to notify top layer ( UI for example) that state has changed ( good example: game).
2) Is there any kind of "bridge" class in RxJava library ( I think about it as "subscribe to it, then you can pass arguments to it as many times as you want and information/observable will be emitted to subscribers).
3) Is there any sense and advanatage of trying to do that instead of standard interface callbacks ( in case like above, not " click button, get response once")
UPDATE, ANSWER BASED ON EXAMPLE ABOVE
As Bob Dalgleish mentioned, way of making such bridge is by using one of the class extending Subject<T> rxjava.
http://reactivex.io/documentation/subject.html
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getCallbackSubjectRx()
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private BehaviorSubject<String> mCallbackRx;
public ClassB() {
mCallbackRx = BehaviorSubject.create();
}
// method somethingHappened can be invoked whenever whe want and
// it will send given parameter to all subscribers
private void somethingHappened() {
mCallbackRx.onNext("method somethingHappened");
}
// multiple subscribers allowed
public BehaviorSubject<String> getCallbackSubjectRx() {
return mCallbackRx;
}
}
Downside might be, that if we want to use one "bridge" to handle multiple callback types ( interface have methods, we use only one method: "onNext()"), we might need to create wrapper class with callback parameters. Which isn't big problem in my opinion.
On the other hand, we get access to all of RxJava operators.
http://reactivex.io/documentation/operators.html
( Example above is for RxJava2, where Disposable is basically Subscription from RxJava1).
The first thing to note is that
CLASS B................↑ returns 0...n observables to observer
is not true. Class B returns an observable, on which it will occasionally emit 0..n values.
(the question is not clear). The inner observable, from class B, is changing state for whatever reason. The most common reason is that another process/task/thread is feeding it, and you want to display the resulting state in the UI.
A simple type of "bridging" class that I use all the time any of the several Subject<> classes. You can emit new values to them using .onNext() and the subscribers will get those values.
If callback interfaces were all standardized, then they would have some advantage, but they vary all over the place. You have to remember that you need some particular interface for this thing you are looking at and and a different one for the other thing. While UI events tend to be quite uniform these days, trying to mix UI events and network events and database events will still leave you feeling overwhelmed. Having a much smaller class of interfaces, mostly encapsulated inside of the rxJava generic classes, makes composing functionality much easier.
Edit: Improve example code.
There is a good article from Yammer Engineering on using Observable.create() (formerly Observable.fromEmitter(), formerly Observable.fromAsync(). The important points he makes are
Using Observable.create() handles the subscription step for you by registering a listener to the underlying interface. More importantly, it arranges to de-register the listener when the unsubscribe() occurs.
Out of the box, this code handles multiple subscribers, each of which receives its own observable stream of data.
As I mentioned above, the listener protocol is particular to the thing you register with. If that thing supports only a single listener, then you will likely want to introduce a Subject that subscribes to the thing under observation, and all your other observers subscribe to the subject.
End of edit.
My favorite example of composition of solutions is the distinctUntilChanged() operator. Because it is an operator that works on a generic observable, it encapsulates the stateful property of saving consecutive values for comparison and only emitting differing ones. I use it frequently for logging state changes. To achieve the same end using standard callback interfaces would require adding a different interface for saving prior values to every existing interface.
So, yes, most of the time it is worth using the rxJava approach of observables, simply for the sake of not having to remember which of the many call back protocols might be applicable in the current case.
I have subscribers that interact with UI components of an activity/fragment. I'm not sure where and when should I unsubscribe them. I see two ways: the former is to unsubscribe them in the onPause() method, the latter is to unsubscribe them in the onStop() method. Which one is correct and why? Thanks
You should use onPause as you don't need the listener running while the activity or fragment is not. onPause gets called everytime the item is no longer activity running. onStop is called on the way to destruction.
"But what if my observable downloads some content after the activity starts"
For long time operations or operations that must be independent from Activity Lifecycle you shuold use Service component
Please take a look at this https://github.com/trello/RxLifecycle. It will prevent your app from throwing NPE on views and context memory leaks.
Read about MVP pattern. Below I made exemplary implementation
Presenter class
public class SamplePresenter {
#NonNull
private final Observable<SomeData> someDataObservable;
public SamplePresenter(#NonNull ApiService apiService) {
someDataObservable = apiService.apiRequest()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());
}
#NonNull
public Observable<SomeData> getSomeDataObservable() {
return someDataObservable;
}
}
MainActivity class
#Inject
SamplePresenter samplePresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
samplePresenter.getSomeDataObservable()
.compose(this.<SomeData>bindToLifecycle())
.subscribe(new Action1<SomeData>() {
#Override
public void call(SomeData someData) {
}
});