This is my answer to this question.
First of all I use this cool method to keep presenter alive even if activity recreated: Presenter surviving orientation changes with Loaders. It detaches and attaches activity in onStop and onStart.
First of all I use this cool method to keep presenter alive even if activity recreated: Presenter surviving orientation changes with Loaders. It detaches and attaches activity in onStop and onStart.
Need to mention also, that your second choice with persistent fragment in widely used, e.g. by Fernando Cejas. I've learned clean architecture approach with his articles, and he uses setRetainState(true).
And still your question is driving me crazy as well. Only solution I've found so far is ugly as hell. But it should work. Idea: after work done, I check if view is attached. If so, I proceed normally. I there is no view, that we are in the middle of rotation. So I have flag, that indicate, that work is done. I turn it on. Also I cache any needed data. And wait for the next view attaching. Where I check that flag.
Here is my code snippet. I'm not proud of it thought.
class SplashPresenter extends BasePresenter<SplashView> {
private final SplashInteractor splashInteractor;
private boolean isSplashWorkStarted;
private boolean isSplashWorkFinished;
private boolean isSplashWorkError;
private Throwable splashWorkError;
@Inject
SplashPresenter(SplashInteractor splashInteractor) {
this.splashInteractor = splashInteractor;
}
@Override
public void attachView(SplashView mvpView) {
super.attachView(mvpView);
if (isSplashWorkFinished) {
getMvpView().showApplicationUi();
} else if (isSplashWorkError) {
getMvpView().showError(splashWorkError.getMessage());
}
}
void executeSplashWork() {
if (!isSplashWorkStarted) {
splashInteractor.execute(new SplashInteractorSubscriber());
isSplashWorkStarted = true;
}
}
@Override
public void onDestroyed() {
splashInteractor.unsubscribe();
}
private final class SplashInteractorSubscriber extends Subscriber<Void> {
@Override
public void onCompleted() {
if (isViewAttached()) {
getMvpView().showApplicationUi();
} else {
isSplashWorkFinished = true;
}
}
@Override
public void onError(Throwable e) {
if (isViewAttached()) {
getMvpView().showError(e.getMessage());
} else {
isSplashWorkError = true;
splashWorkError = e;
}
}
@Override
public void onNext(Void v) {
}
}
}