diff --git a/sample/src/main/java/com/uber/autodispose/recipes/AutoDisposeViewHolder.java b/sample/src/main/java/com/uber/autodispose/recipes/AutoDisposeViewHolder.java index 44c2329b2..d64f3a846 100644 --- a/sample/src/main/java/com/uber/autodispose/recipes/AutoDisposeViewHolder.java +++ b/sample/src/main/java/com/uber/autodispose/recipes/AutoDisposeViewHolder.java @@ -16,51 +16,68 @@ package com.uber.autodispose.recipes; -import android.support.annotation.Nullable; import android.support.v7.widget.BindAwareViewHolder; import android.view.View; -import com.uber.autodispose.ScopeProvider; -import io.reactivex.Maybe; -import io.reactivex.subjects.MaybeSubject; + +import com.uber.autodispose.LifecycleEndedException; +import com.uber.autodispose.LifecycleScopeProvider; + +import javax.annotation.Nullable; + +import io.reactivex.Observable; +import io.reactivex.functions.Function; +import io.reactivex.subjects.BehaviorSubject; /** * Example implementation of a {@link android.support.v7.widget.RecyclerView.ViewHolder} - * implementation that implements {@link ScopeProvider}. This could be useful for cases where you - * have subscriptions that should be disposed upon unbinding or otherwise aren't overwritten - * in future binds. + * implementation that implements {@link LifecycleScopeProvider}. This could be useful for cases + * where you have subscriptions that should be disposed upon unbinding or otherwise aren't + * overwritten in future binds. */ -public abstract class AutoDisposeViewHolder extends BindAwareViewHolder implements ScopeProvider { +public abstract class AutoDisposeViewHolder + extends BindAwareViewHolder + implements LifecycleScopeProvider { + + public enum ViewHolderEvent { + BIND, UNBIND + } - private static final Object NOTIFICATION = new Object(); + private static final Function CORRESPONDING_EVENTS = + new Function() { + @Override + public ViewHolderEvent apply(final ViewHolderEvent viewHolderEvent) throws Exception { + switch (viewHolderEvent) { + case BIND: + return ViewHolderEvent.UNBIND; + default: + throw new LifecycleEndedException("Cannot use ViewHolder lifecycle after unbind."); + } + } + }; - @Nullable private MaybeSubject unbindNotifier = null; + private final BehaviorSubject lifecycleEvents = BehaviorSubject.create(); public AutoDisposeViewHolder(View itemView) { super(itemView); } - private synchronized MaybeSubject notifier() { - MaybeSubject n = unbindNotifier; - if (n == null) { - n = MaybeSubject.create(); - unbindNotifier = n; - } - return n; + @Override public Function correspondingEvents() { + return CORRESPONDING_EVENTS; } - @Override protected void onUnbind() { - emitUnbindIfPresent(); - unbindNotifier = null; + @Override public Observable lifecycle() { + return lifecycleEvents.hide(); + } + + @Nullable @Override public ViewHolderEvent peekLifecycle() { + return lifecycleEvents.getValue(); } - private void emitUnbindIfPresent() { - MaybeSubject notifier = unbindNotifier; - if (notifier != null && !notifier.hasComplete()) { - notifier.onSuccess(NOTIFICATION); - } + @Override protected void onBind() { + lifecycleEvents.onNext(ViewHolderEvent.BIND); } - @Override public final Maybe requestScope() { - return notifier(); + @Override protected void onUnbind() { + lifecycleEvents.onNext(ViewHolderEvent.UNBIND); } } diff --git a/sample/src/main/kotlin/com/uber/autodispose/recipes/AutoDisposeViewHolderKotlin.kt b/sample/src/main/kotlin/com/uber/autodispose/recipes/AutoDisposeViewHolderKotlin.kt index 904d75d2f..8086884ce 100644 --- a/sample/src/main/kotlin/com/uber/autodispose/recipes/AutoDisposeViewHolderKotlin.kt +++ b/sample/src/main/kotlin/com/uber/autodispose/recipes/AutoDisposeViewHolderKotlin.kt @@ -19,44 +19,47 @@ package com.uber.autodispose.recipes import android.support.v7.widget.BindAwareViewHolder import android.support.v7.widget.RecyclerView.ViewHolder import android.view.View -import com.uber.autodispose.ScopeProvider -import io.reactivex.Maybe -import io.reactivex.subjects.MaybeSubject +import com.uber.autodispose.LifecycleEndedException +import com.uber.autodispose.LifecycleScopeProvider +import com.uber.autodispose.recipes.AutoDisposeViewHolderKotlin.ViewHolderEvent.BIND +import com.uber.autodispose.recipes.AutoDisposeViewHolderKotlin.ViewHolderEvent.UNBIND +import io.reactivex.Observable +import io.reactivex.functions.Function +import io.reactivex.subjects.BehaviorSubject private object NOTIFICATION /** * Example implementation of a [ViewHolder] implementation that implements - * [ScopeProvider]. This could be useful for cases where you have subscriptions that should be + * [LifecycleScopeProvider]. This could be useful for cases where you have subscriptions that should be * disposed upon unbinding or otherwise aren't overwritten in future binds. */ abstract class AutoDisposeViewHolderKotlin(itemView: View) - : BindAwareViewHolder(itemView), ScopeProvider { + : BindAwareViewHolder(itemView), LifecycleScopeProvider { - private var unbindNotifier: MaybeSubject? = null + private val lifecycleEvents by lazy { BehaviorSubject.create() } - private val notifier: MaybeSubject - get() { - synchronized(this) { - return unbindNotifier ?: MaybeSubject.create().also { unbindNotifier = it } - } - } - - override fun onUnbind() { - emitUnbindIfPresent() - unbindNotifier = null + enum class ViewHolderEvent { + BIND, UNBIND } - private fun emitUnbindIfPresent() { - unbindNotifier?.let { - if (!it.hasComplete()) { - it.onSuccess(NOTIFICATION) + override fun onBind() = lifecycleEvents.onNext(BIND) + + override fun onUnbind() = lifecycleEvents.onNext(UNBIND) + + override fun lifecycle(): Observable = lifecycleEvents.hide() + + override fun correspondingEvents(): Function = CORRESPONDING_EVENTS + + override fun peekLifecycle(): ViewHolderEvent? = lifecycleEvents.value + + companion object { + + private val CORRESPONDING_EVENTS = Function { viewHolderEvent -> + when (viewHolderEvent) { + BIND -> UNBIND + else -> throw LifecycleEndedException("Cannot use ViewHolder lifecycle after unbind.") } } } - - override fun requestScope(): Maybe<*> { - return notifier - } - }