0
votes

I have a series of sequential Parse network calls that are all dependent on each other to save the final object all wrapped by an Observable so I can deal with everything as one call in my presenter.

If the user decides to change fragments, or leave the app or whatever, this network call is important enough that I'd like it to attempt to complete.

If I call disposables.dispose() the observable will throw an error (which I can catch) on the next .save method in the Observable and the network call does not finish.

If I don't dispose of it, the network call finishes, but it will call my onComplete and throw an error since the view is gone. I can stop that error from happening, but then I'm worried that I've created a memory leak.

I don't care if the oncomplete/onerror get called if the user gets into this situation but I would like to ensure it completes one way or another.

Is there any way to let the call complete, but not cause a memory leak by not disposing it?

fun doParseNetworkCall(){
  return Observable.create<Boolean> { emitter ->
    createParseObject1
    createParseObject1.save()

    createParseObject2
    createParseObject2.add(key, createParseObject1)
    createParseObject2.save()

    createParseObject3
    createParseObject3.add(key, createParseObject2)
    createParseObject3.save()

    emitter.onNext(true)
}


fun doNetworkCall(){
    repo.doParseNetworkCall()
        .observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io()).subscribeBy(
            onError = { error ->
                //do something
            },
            onComplete = {
               //do something
            }
        ).addTo(disposable)
}
1
The stream is over if onComplete() or onError() got called, you don't need to dispose in this casey.allam
If onComplete or onError gets called it'd crash from accessing a view that was detached. I tried putting logic in that if I switched fragments to not call onComplete/onError, but thats where I'm worried about a memory leak. How could I have onComplete call but not crash when it accesses the view? Wrap the whole oncomplete/onerror on if View != null?Ben987654
How about subscribing with an observer that does nothing, then subscribe with the one that updates the UI. This way when you dispose the UI observer the stream will continue because it still has an observer subscribed. May be not the cleanest way, but i think it'll get the job doney.allam
If your api calls are independent of Activity/Fragment then you would have to call the api in service (may be intent service) and provide call back to activity or fragment.Moinkhan
If I have to use an intent service I will, but kind of hoping to avoid that. Since I don't care about what it returns if the screens have changed I was hoping there might be a way to do it without that. I'll give that idea of 2 subscribers a try in the morning.Ben987654

1 Answers

0
votes

I was able to resolve my issue doing the following. I think it's memory safe since the 2nd set of observables don't subscribe until the first observable completes, and if the Composite Disposable in the presenter has been disposed of already, the 2nd set will not subscribe.

repo.saveSomething()
                .map {
                    //Do some non view stuff
                }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io()).subscribeBy(
                    onError = { error ->
                       onErrorMethod()
                    },
                    onComplete = {
                       onSuccessMethod()
                    }
                )

 fun onSuccessMethod() {
        Observable.just(true)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io()).subscribeBy(
                onComplete = {
                   //Do view stuff
                }).addTo(disposable)
    }

fun onErrorMethod() {
        Observable.just(true)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io()).subscribeBy(
                onComplete = {
                   //Do view stuff
                }).addTo(disposable)
    }