Skip to content

Commit

Permalink
Make AndroidLifecycleScopeProvider reusable by backfilling from peek
Browse files Browse the repository at this point in the history
This moves backfilling out of a one-time thing in the constructor to something we do every time the lifecycle is peeked. It feels a bit weird though, but perhaps necessary because of the fact that arch lifecycle events are emitted _after_ the corresponding callback method.

Resolves #114
  • Loading branch information
ZacSweers committed Oct 22, 2017
1 parent 60d95bf commit b215346
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public final class AndroidLifecycleScopeProvider
case ON_STOP:
case ON_DESTROY:
default:
throw new LifecycleEndedException();
throw new LifecycleEndedException("Lifecycle has ended! Last event was " + lastEvent);
}
}
};
Expand Down Expand Up @@ -145,6 +145,7 @@ private AndroidLifecycleScopeProvider(Lifecycle lifecycle,
}

@Override public Lifecycle.Event peekLifecycle() {
lifecycleObservable.backfillEvents();
return lifecycleObservable.getValue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,36 @@

@SuppressWarnings("CheckReturnValue") LifecycleEventsObservable(Lifecycle lifecycle) {
this.lifecycle = lifecycle;
}

Event getValue() {
return eventsObservable.getValue();
}

void backfillEvents() {
// Backfill if already created for boundary checking
// We do a trick here for corresponding events where we pretend something is created
// upon initialized state so that it assumes the corresponding event is DESTROY.
@Nullable Event correspondingEvent;
@Nullable Lifecycle.Event correspondingEvent;
switch (lifecycle.getCurrentState()) {
case INITIALIZED:
correspondingEvent = Event.ON_CREATE;
correspondingEvent = Lifecycle.Event.ON_CREATE;
break;
case CREATED:
correspondingEvent = Event.ON_START;
correspondingEvent = Lifecycle.Event.ON_START;
break;
case STARTED:
case RESUMED:
correspondingEvent = Event.ON_RESUME;
correspondingEvent = Lifecycle.Event.ON_RESUME;
break;
case DESTROYED:
default:
correspondingEvent = Event.ON_DESTROY;
correspondingEvent = Lifecycle.Event.ON_DESTROY;
break;
}
eventsObservable.onNext(correspondingEvent);
}

Event getValue() {
return eventsObservable.getValue();
}

@Override protected void subscribeActual(Observer<? super Event> observer) {
if (!isMainThread()) {
observer.onError(
Expand Down Expand Up @@ -97,7 +100,7 @@ static final class ArchLifecycleObserver extends MainThreadDisposable
@OnLifecycleEvent(Event.ON_ANY) void onStateChange(LifecycleOwner owner, Event event) {
if (!isDisposed()) {
if (!(event == Event.ON_CREATE && eventsObservable.getValue() == event)) {
// Due to the INITIALIZED->ON_CREATE mapping trick we do in the constructor backfill,
// Due to the INITIALIZED->ON_CREATE mapping trick we do in backfill(),
// we fire this conditionally to avoid duplicate CREATE events.
eventsObservable.onNext(event);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import java.util.concurrent.TimeUnit
*/
class KotlinActivity : AppCompatActivity() {

// Can be reused
private val scopeProvider by lazy { AndroidLifecycleScopeProvider.from(this) }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate()")
Expand All @@ -41,7 +44,7 @@ class KotlinActivity : AppCompatActivity() {
// dispose is onDestroy (the opposite of onCreate).
Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose { Log.i(TAG, "Disposing subscription from onCreate()") }
.autoDisposeWith(AndroidLifecycleScopeProvider.from(this))
.autoDisposeWith(scopeProvider)
.subscribe { num -> Log.i(TAG, "Started in onCreate(), running until onDestroy(): " + num) }
}

Expand All @@ -54,7 +57,7 @@ class KotlinActivity : AppCompatActivity() {
// dispose is onStop (the opposite of onStart).
Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose { Log.i(TAG, "Disposing subscription from onStart()") }
.autoDisposeWith(AndroidLifecycleScopeProvider.from(this))
.autoDisposeWith(scopeProvider)
.subscribe { num -> Log.i(TAG, "Started in onStart(), running until in onStop(): " + num) }
}

Expand All @@ -67,7 +70,7 @@ class KotlinActivity : AppCompatActivity() {
// dispose is onPause (the opposite of onResume).
Observable.interval(1, TimeUnit.SECONDS)
.doOnDispose { Log.i(TAG, "Disposing subscription from onResume()") }
.autoDisposeWith(AndroidLifecycleScopeProvider.from(this))
.autoDisposeWith(scopeProvider)
.subscribe { num ->
Log.i(TAG, "Started in onResume(), running until in onPause(): " + num)
}
Expand Down

0 comments on commit b215346

Please sign in to comment.