diff --git a/build.gradle b/build.gradle index f7966fa..f5f84d5 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'com.android.library' apply plugin: 'me.tatarka.retrolambda' android { - compileSdkVersion 23 - buildToolsVersion "23.0.3" + compileSdkVersion 24 + buildToolsVersion "24.0.1" compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -12,13 +12,15 @@ android { defaultConfig { minSdkVersion 9 - targetSdkVersion 23 + targetSdkVersion 24 } } dependencies { compile project(':libraries:core') - - provided 'com.android.support:appcompat-v7:23.4.0' - provided 'io.reactivex:rxandroid:1.2.0' + + provided 'com.android.support:appcompat-v7:24.1.1' + compile 'com.android.support:recyclerview-v7:24.1.1' + + provided 'io.reactivex:rxandroid:1.2.1' } diff --git a/src/main/java/ru/touchin/roboswag/components/adapters/BindableViewHolder.java b/src/main/java/ru/touchin/roboswag/components/adapters/BindableViewHolder.java new file mode 100644 index 0000000..7756014 --- /dev/null +++ b/src/main/java/ru/touchin/roboswag/components/adapters/BindableViewHolder.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015 RoboSwag (Gavriil Sitnikov, Vsevolod Ivanov) + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.roboswag.components.adapters; + +import android.support.annotation.CallSuper; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import java.util.concurrent.TimeUnit; + +import ru.touchin.roboswag.components.utils.LifecycleBindable; +import ru.touchin.roboswag.core.log.Lc; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action0; +import rx.functions.Action1; +import rx.subjects.BehaviorSubject; + +/** + * Created by Gavriil Sitnikov on 12/8/2016. + * TODO: fill description + */ +public class BindableViewHolder extends RecyclerView.ViewHolder implements LifecycleBindable { + + // it is needed to delay detach to avoid re-subscriptions on fast scroll + private static final long DETACH_DELAY = TimeUnit.SECONDS.toMillis(1); + + @NonNull + private final LifecycleBindable baseLifecycleBindable; + @NonNull + private final BehaviorSubject attachedToWindowSubject = BehaviorSubject.create(); + private final Observable attachedObservable; + + public BindableViewHolder(@NonNull final LifecycleBindable baseLifecycleBindable, @NonNull final View itemView) { + super(itemView); + this.baseLifecycleBindable = baseLifecycleBindable; + attachedObservable = attachedToWindowSubject + .switchMap(attached -> attached + ? Observable.just(true) + : Observable.timer(DETACH_DELAY, TimeUnit.MILLISECONDS).map(ignored -> false)) + .distinctUntilChanged() + .replay(1) + .refCount(); + } + + @CallSuper + public void onAttachedToWindow() { + attachedToWindowSubject.onNext(true); + } + + public boolean isAttachedToWindow() { + return attachedToWindowSubject.hasValue() && attachedToWindowSubject.getValue(); + } + + @CallSuper + public void onDetachedFromWindow() { + attachedToWindowSubject.onNext(false); + } + + @SuppressWarnings("CPD-START") + //CPD: it is same as in other implementation based on BaseLifecycleBindable + @NonNull + @Override + public Subscription bind(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { + final Observable safeObservable = observable + .onErrorResumeNext(throwable -> { + Lc.assertion(throwable); + return Observable.never(); + }) + .observeOn(AndroidSchedulers.mainThread()); + return attachedObservable.switchMap(attached -> attached ? safeObservable : Observable.never()) + .subscribe(onNextAction); + } + + @NonNull + @Override + public Subscription untilStop(@NonNull final Observable observable) { + return baseLifecycleBindable.untilStop(observable); + } + + @NonNull + @Override + public Subscription untilStop(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { + return baseLifecycleBindable.untilStop(observable, onNextAction); + } + + @NonNull + @Override + public Subscription untilStop(@NonNull final Observable observable, + @NonNull final Action1 onNextAction, + @NonNull final Action1 onErrorAction) { + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction); + } + + @NonNull + @Override + public Subscription untilStop(@NonNull final Observable observable, + @NonNull final Action1 onNextAction, + @NonNull final Action1 onErrorAction, + @NonNull final Action0 onCompletedAction) { + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction); + } + + @NonNull + @Override + public Subscription untilDestroy(@NonNull final Observable observable) { + return baseLifecycleBindable.untilDestroy(observable); + } + + @NonNull + @Override + public Subscription untilDestroy(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { + return baseLifecycleBindable.untilDestroy(observable, onNextAction); + } + + @NonNull + @Override + public Subscription untilDestroy(@NonNull final Observable observable, + @NonNull final Action1 onNextAction, + @NonNull final Action1 onErrorAction) { + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction); + } + + @NonNull + @Override + public Subscription untilDestroy(@NonNull final Observable observable, + @NonNull final Action1 onNextAction, + @NonNull final Action1 onErrorAction, + @NonNull final Action0 onCompletedAction) { + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction); + } + +} diff --git a/src/main/java/ru/touchin/roboswag/components/adapters/ObservableCollectionAdapter.java b/src/main/java/ru/touchin/roboswag/components/adapters/ObservableCollectionAdapter.java new file mode 100644 index 0000000..a47a21e --- /dev/null +++ b/src/main/java/ru/touchin/roboswag/components/adapters/ObservableCollectionAdapter.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2015 RoboSwag (Gavriil Sitnikov, Vsevolod Ivanov) + * + * This file is part of RoboSwag library. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package ru.touchin.roboswag.components.adapters; + +import android.os.Looper; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import ru.touchin.roboswag.components.utils.LifecycleBindable; +import ru.touchin.roboswag.components.utils.UiUtils; +import ru.touchin.roboswag.core.log.Lc; +import ru.touchin.roboswag.core.observables.collections.Change; +import ru.touchin.roboswag.core.observables.collections.ObservableCollection; +import ru.touchin.roboswag.core.observables.collections.ObservableList; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Actions; +import rx.subjects.BehaviorSubject; + +/** + * Created by Gavriil Sitnikov on 20/11/2015. + * TODO: fill description + */ +public abstract class ObservableCollectionAdapter + extends RecyclerView.Adapter { + + private static final int PRE_LOADING_COUNT = 10; + + private static final int LIST_ITEM_TYPE = 12313212; + + @NonNull + private final BehaviorSubject> observableCollectionSubject + = BehaviorSubject.create((ObservableCollection) null); + @NonNull + private final LifecycleBindable lifecycleBindable; + @Nullable + private OnItemClickListener onItemClickListener; + private int lastUpdatedChangeNumber = -1; + @NonNull + private final Observable historyPreLoadingObservable; + + @NonNull + private final ObservableList innerCollection = new ObservableList<>(); + private boolean anyChangeApplied; + @NonNull + private final List attachedRecyclerViews = new LinkedList<>(); + + public ObservableCollectionAdapter(@NonNull final LifecycleBindable lifecycleBindable) { + super(); + this.lifecycleBindable = lifecycleBindable; + innerCollection.observeChanges().subscribe(this::onItemsChanged); + lifecycleBindable.untilDestroy(observableCollectionSubject + .doOnNext(collection -> innerCollection.set(collection != null ? collection.getItems() : new ArrayList<>())) + .switchMap(observableCollection -> observableCollection != null + ? observableCollection.observeChanges().observeOn(AndroidSchedulers.mainThread()) + : Observable.empty()), + changes -> { + anyChangeApplied = true; + for (final Change change : changes.getChanges()) { + switch (change.getType()) { + case INSERTED: + innerCollection.addAll(change.getStart(), change.getChangedItems()); + break; + case CHANGED: + innerCollection.update(change.getStart(), change.getChangedItems()); + break; + case REMOVED: + innerCollection.remove(change.getStart(), change.getCount()); + break; + default: + Lc.assertion("Not supported " + change.getType()); + break; + } + } + }); + historyPreLoadingObservable = observableCollectionSubject + .switchMap(observableCollection -> { + final int size = observableCollection.size(); + return observableCollection.loadRange(size, size + PRE_LOADING_COUNT); + }); + } + + @Override + public void onAttachedToRecyclerView(@NonNull final RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + attachedRecyclerViews.add(recyclerView); + } + + @Override + public void onDetachedFromRecyclerView(@NonNull final RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + attachedRecyclerViews.remove(recyclerView); + } + + @NonNull + public LifecycleBindable getLifecycleBindable() { + return lifecycleBindable; + } + + protected long getItemClickDelay() { + return UiUtils.RIPPLE_EFFECT_DELAY; + } + + public void setItems(@NonNull final List items) { + setObservableCollection(new ObservableList<>(items)); + } + + @Nullable + public ObservableCollection getObservableCollection() { + return observableCollectionSubject.getValue(); + } + + @NonNull + public Observable> observeObservableCollection() { + return observableCollectionSubject.distinctUntilChanged(); + } + + protected int getHeadersCount() { + return 0; + } + + protected int getFootersCount() { + return 0; + } + + private void refreshUpdate() { + notifyDataSetChanged(); + lastUpdatedChangeNumber = innerCollection.getChangesCount(); + } + + public void setObservableCollection(@Nullable final ObservableCollection observableCollection) { + this.observableCollectionSubject.onNext(observableCollection); + refreshUpdate(); + } + + private boolean anyRecyclerViewShown() { + for (final RecyclerView recyclerView : attachedRecyclerViews) { + if (recyclerView.isShown()) { + return true; + } + } + return false; + } + + protected void onItemsChanged(@NonNull final ObservableCollection.CollectionChange collectionChange) { + if (Looper.myLooper() != Looper.getMainLooper()) { + Lc.assertion("Items changes called on not main thread"); + return; + } + if (!anyChangeApplied || !anyRecyclerViewShown()) { + anyChangeApplied = true; + refreshUpdate(); + return; + } + if (collectionChange.getNumber() != innerCollection.getChangesCount() + || collectionChange.getNumber() != lastUpdatedChangeNumber + 1) { + if (lastUpdatedChangeNumber < collectionChange.getNumber()) { + refreshUpdate(); + } + return; + } + notifyAboutChanges(collectionChange.getChanges()); + lastUpdatedChangeNumber = innerCollection.getChangesCount(); + } + + private void notifyAboutChanges(@NonNull final Collection> changes) { + for (final Change change : changes) { + switch (change.getType()) { + case INSERTED: + notifyItemRangeInserted(change.getStart() + getHeadersCount(), change.getCount()); + break; + case CHANGED: + notifyItemRangeChanged(change.getStart() + getHeadersCount(), change.getCount()); + break; + case REMOVED: + if (getItemCount() == 0) { + //TODO: bug of recyclerview? + notifyDataSetChanged(); + } else { + notifyItemRangeRemoved(change.getStart() + getHeadersCount(), change.getCount()); + } + break; + default: + Lc.assertion("Not supported " + change.getType()); + break; + } + } + } + + public void setOnItemClickListener(@Nullable final OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + refreshUpdate(); + } + + @Override + public int getItemViewType(final int position) { + return LIST_ITEM_TYPE; + } + + @Override + public BindableViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) { + return onCreateItemViewHolder(parent, viewType); + } + + public abstract TViewHolder onCreateItemViewHolder(@NonNull ViewGroup parent, int viewType); + + @SuppressWarnings("unchecked") + @Override + public void onBindViewHolder(final BindableViewHolder holder, final int position) { + lastUpdatedChangeNumber = innerCollection.getChangesCount(); + + if (position - getHeadersCount() >= innerCollection.size()) { + return; + } + final TItem item = innerCollection.get(position - getHeadersCount()); + + onBindItemToViewHolder((TViewHolder) holder, position, item); + ((TViewHolder) holder).bindPosition(position); + if (onItemClickListener != null && !isOnClickListenerDisabled(item)) { + UiUtils.setOnRippleClickListener(holder.itemView, () -> onItemClickListener.onItemClicked(item, position), getItemClickDelay()); + } + } + + protected abstract void onBindItemToViewHolder(@NonNull TViewHolder holder, int position, @NonNull TItem item); + + @Nullable + public TItem getItem(final int position) { + final int positionInList = position - getHeadersCount(); + return positionInList >= innerCollection.size() ? null : innerCollection.get(positionInList); + } + + @Override + public int getItemCount() { + return getHeadersCount() + innerCollection.size() + getFootersCount(); + } + + @Override + public void onViewAttachedToWindow(@NonNull final BindableViewHolder holder) { + super.onViewAttachedToWindow(holder); + holder.onAttachedToWindow(); + } + + @Override + public void onViewDetachedFromWindow(@NonNull final BindableViewHolder holder) { + holder.onDetachedFromWindow(); + super.onViewDetachedFromWindow(holder); + } + + public boolean isOnClickListenerDisabled(@NonNull final TItem item) { + return false; + } + + public interface OnItemClickListener { + + void onItemClicked(@NonNull TItem item, int position); + + } + + public class ViewHolder extends BindableViewHolder { + + @Nullable + private Subscription historyPreLoadingSubscription; + + public ViewHolder(@NonNull final LifecycleBindable baseBindable, @NonNull final View itemView) { + super(baseBindable, itemView); + } + + @SuppressWarnings("unchecked") + public void bindPosition(final int position) { + if (historyPreLoadingSubscription != null) { + historyPreLoadingSubscription.unsubscribe(); + historyPreLoadingSubscription = null; + } + if (position - getHeadersCount() > innerCollection.size() - PRE_LOADING_COUNT) { + historyPreLoadingSubscription = bind(historyPreLoadingObservable, Actions.empty()); + } + } + + } + +} diff --git a/src/main/java/ru/touchin/roboswag/components/navigation/ViewController.java b/src/main/java/ru/touchin/roboswag/components/navigation/ViewController.java index 61352f6..13ef9e1 100644 --- a/src/main/java/ru/touchin/roboswag/components/navigation/ViewController.java +++ b/src/main/java/ru/touchin/roboswag/components/navigation/ViewController.java @@ -33,8 +33,8 @@ import android.view.ViewGroup; import ru.touchin.roboswag.components.navigation.activities.ViewControllerActivity; import ru.touchin.roboswag.components.navigation.fragments.ViewControllerFragment; -import ru.touchin.roboswag.components.observables.ui.BaseUiBindable; -import ru.touchin.roboswag.components.observables.ui.UiBindable; +import ru.touchin.roboswag.components.utils.BaseLifecycleBindable; +import ru.touchin.roboswag.components.utils.LifecycleBindable; import rx.Observable; import rx.Subscription; import rx.functions.Action0; @@ -49,7 +49,7 @@ import rx.functions.Action1; */ public class ViewController, TFragment extends ViewControllerFragment> - implements UiBindable { + implements LifecycleBindable { @NonNull private final TActivity activity; @@ -58,13 +58,12 @@ public class ViewController, @NonNull private final ViewGroup container; @NonNull - private final BaseUiBindable baseUiBindable = new BaseUiBindable(); + private final BaseLifecycleBindable baseLifecycleBindable = new BaseLifecycleBindable(); private boolean destroyed; @SuppressWarnings({"unchecked", "PMD.UnusedFormalParameter"}) //UnusedFormalParameter: savedInstanceState could be used by children - public ViewController(@NonNull final CreationContext creationContext, - @Nullable final Bundle savedInstanceState) { + public ViewController(@NonNull final CreationContext creationContext, @Nullable final Bundle savedInstanceState) { this.activity = (TActivity) creationContext.activity; this.fragment = (TFragment) creationContext.fragment; this.container = creationContext.container; @@ -147,7 +146,7 @@ public class ViewController, */ @CallSuper public void onCreate() { - baseUiBindable.onCreate(); + baseLifecycleBindable.onCreate(); } /** @@ -156,7 +155,7 @@ public class ViewController, */ @CallSuper public void onStart() { - baseUiBindable.onStart(); + baseLifecycleBindable.onStart(); } /** @@ -175,7 +174,7 @@ public class ViewController, */ @CallSuper public void onStop() { - baseUiBindable.onStop(); + baseLifecycleBindable.onStop(); } /** @@ -184,7 +183,7 @@ public class ViewController, */ @CallSuper public void onDestroy() { - baseUiBindable.onDestroy(); + baseLifecycleBindable.onDestroy(); destroyed = true; } @@ -199,23 +198,23 @@ public class ViewController, } @SuppressWarnings("CPD-START") - //CPD: it is same as in other implementation based on BaseUiBindable + //CPD: it is same as in other implementation based on BaseLifecycleBindable @NonNull @Override public Subscription bind(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.bind(observable, onNextAction); + return baseLifecycleBindable.bind(observable, onNextAction); } @NonNull @Override public Subscription untilStop(@NonNull final Observable observable) { - return baseUiBindable.untilStop(observable); + return baseLifecycleBindable.untilStop(observable); } @NonNull @Override public Subscription untilStop(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.untilStop(observable, onNextAction); + return baseLifecycleBindable.untilStop(observable, onNextAction); } @NonNull @@ -223,7 +222,7 @@ public class ViewController, public Subscription untilStop(@NonNull final Observable observable, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction) { - return baseUiBindable.untilStop(observable, onNextAction, onErrorAction); + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction); } @NonNull @@ -232,19 +231,19 @@ public class ViewController, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction, @NonNull final Action0 onCompletedAction) { - return baseUiBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction); + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction); } @NonNull @Override public Subscription untilDestroy(@NonNull final Observable observable) { - return baseUiBindable.untilDestroy(observable); + return baseLifecycleBindable.untilDestroy(observable); } @NonNull @Override public Subscription untilDestroy(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.untilDestroy(observable, onNextAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction); } @NonNull @@ -252,7 +251,7 @@ public class ViewController, public Subscription untilDestroy(@NonNull final Observable observable, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction) { - return baseUiBindable.untilDestroy(observable, onNextAction, onErrorAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction); } @NonNull @@ -261,11 +260,11 @@ public class ViewController, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction, @NonNull final Action0 onCompletedAction) { - return baseUiBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction); } @SuppressWarnings("CPD-END") - //CPD: it is same as in other implementation based on BaseUiBindable + //CPD: it is same as in other implementation based on BaseLifecycleBindable /** * Helper class to simplify constructor override. */ diff --git a/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.java b/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.java index f118cb4..c3b5bf5 100644 --- a/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.java +++ b/src/main/java/ru/touchin/roboswag/components/navigation/activities/BaseActivity.java @@ -29,8 +29,8 @@ import android.view.inputmethod.InputMethodManager; import java.util.ArrayList; -import ru.touchin.roboswag.components.observables.ui.BaseUiBindable; -import ru.touchin.roboswag.components.observables.ui.UiBindable; +import ru.touchin.roboswag.components.utils.BaseLifecycleBindable; +import ru.touchin.roboswag.components.utils.LifecycleBindable; import rx.Observable; import rx.Subscription; import rx.functions.Action0; @@ -42,12 +42,12 @@ import rx.functions.Action1; */ @SuppressWarnings("PMD.TooManyMethods") public abstract class BaseActivity extends AppCompatActivity - implements UiBindable { + implements LifecycleBindable { @NonNull private final ArrayList onBackPressedListeners = new ArrayList<>(); @NonNull - private final BaseUiBindable baseUiBindable = new BaseUiBindable(); + private final BaseLifecycleBindable baseLifecycleBindable = new BaseLifecycleBindable(); private boolean resumed; /** @@ -62,13 +62,13 @@ public abstract class BaseActivity extends AppCompatActivity @Override protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - baseUiBindable.onCreate(); + baseLifecycleBindable.onCreate(); } @Override protected void onStart() { super.onStart(); - baseUiBindable.onStart(); + baseLifecycleBindable.onStart(); } @Override @@ -85,13 +85,13 @@ public abstract class BaseActivity extends AppCompatActivity @Override protected void onStop() { - baseUiBindable.onStop(); + baseLifecycleBindable.onStop(); super.onStop(); } @Override protected void onDestroy() { - baseUiBindable.onDestroy(); + baseLifecycleBindable.onDestroy(); super.onDestroy(); } @@ -146,11 +146,11 @@ public abstract class BaseActivity extends AppCompatActivity } @SuppressWarnings("CPD-START") - //CPD: it is same as in other implementation based on BaseUiBindable + //CPD: it is same as in other implementation based on BaseLifecycleBindable @NonNull @Override public Subscription bind(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.bind(observable, onNextAction); + return baseLifecycleBindable.bind(observable, onNextAction); } @NonNull @@ -158,7 +158,7 @@ public abstract class BaseActivity extends AppCompatActivity public Subscription untilStop(@NonNull final Observable observable, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction) { - return baseUiBindable.untilStop(observable, onNextAction, onErrorAction); + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction); } @NonNull @@ -167,31 +167,31 @@ public abstract class BaseActivity extends AppCompatActivity @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction, @NonNull final Action0 onCompletedAction) { - return baseUiBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction); + return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction); } @NonNull @Override public Subscription untilStop(@NonNull final Observable observable) { - return baseUiBindable.untilStop(observable); + return baseLifecycleBindable.untilStop(observable); } @NonNull @Override public Subscription untilStop(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.untilStop(observable, onNextAction); + return baseLifecycleBindable.untilStop(observable, onNextAction); } @NonNull @Override public Subscription untilDestroy(@NonNull final Observable observable) { - return baseUiBindable.untilDestroy(observable); + return baseLifecycleBindable.untilDestroy(observable); } @NonNull @Override public Subscription untilDestroy(@NonNull final Observable observable, @NonNull final Action1 onNextAction) { - return baseUiBindable.untilDestroy(observable, onNextAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction); } @NonNull @@ -199,7 +199,7 @@ public abstract class BaseActivity extends AppCompatActivity public Subscription untilDestroy(@NonNull final Observable observable, @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction) { - return baseUiBindable.untilDestroy(observable, onNextAction, onErrorAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction); } @NonNull @@ -208,11 +208,11 @@ public abstract class BaseActivity extends AppCompatActivity @NonNull final Action1 onNextAction, @NonNull final Action1 onErrorAction, @NonNull final Action0 onCompletedAction) { - return baseUiBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction); + return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction); } @SuppressWarnings("CPD-END") - //CPD: it is same as in other implementation based on BaseUiBindable + //CPD: it is same as in other implementation based on BaseLifecycleBindable /** * Interface to be implemented for someone who want to intercept device back button pressing event. */ diff --git a/src/main/java/ru/touchin/roboswag/components/observables/ui/BaseUiBindable.java b/src/main/java/ru/touchin/roboswag/components/utils/BaseLifecycleBindable.java similarity index 92% rename from src/main/java/ru/touchin/roboswag/components/observables/ui/BaseUiBindable.java rename to src/main/java/ru/touchin/roboswag/components/utils/BaseLifecycleBindable.java index c8d1f20..a0f8891 100644 --- a/src/main/java/ru/touchin/roboswag/components/observables/ui/BaseUiBindable.java +++ b/src/main/java/ru/touchin/roboswag/components/utils/BaseLifecycleBindable.java @@ -17,7 +17,7 @@ * */ -package ru.touchin.roboswag.components.observables.ui; +package ru.touchin.roboswag.components.utils; import android.support.annotation.NonNull; @@ -32,9 +32,9 @@ import rx.subjects.BehaviorSubject; /** * Created by Gavriil Sitnikov on 18/04/16. - * Simple implementation of {@link UiBindable}. Could be used to not implement interface but use such object inside. + * Simple implementation of {@link LifecycleBindable}. Could be used to not implement interface but use such object inside. */ -public class BaseUiBindable implements UiBindable { +public class BaseLifecycleBindable implements LifecycleBindable { @NonNull private final BehaviorSubject isCreatedSubject = BehaviorSubject.create(); @@ -78,7 +78,7 @@ public class BaseUiBindable implements UiBindable { return Observable.never(); }) .observeOn(AndroidSchedulers.mainThread()); - return isStartedSubject.switchMap(isStarted -> isStarted ? safeObservable : Observable.never()) + return isStartedSubject.switchMap(started -> started ? safeObservable : Observable.never()) .takeUntil(isCreatedSubject.filter(created -> !created)) .subscribe(onNextAction); } @@ -148,7 +148,7 @@ public class BaseUiBindable implements UiBindable { @NonNull final Action1 onErrorAction, @NonNull final Action0 onCompletedAction) { return isCreatedSubject.first() - .switchMap(isCreated -> isCreated ? observable.observeOn(AndroidSchedulers.mainThread()) : Observable.empty()) + .switchMap(created -> created ? observable.observeOn(AndroidSchedulers.mainThread()) : Observable.empty()) .takeUntil(conditionSubject.filter(condition -> condition)) .subscribe(onNextAction, onErrorAction, onCompletedAction); } diff --git a/src/main/java/ru/touchin/roboswag/components/observables/ui/UiBindable.java b/src/main/java/ru/touchin/roboswag/components/utils/LifecycleBindable.java similarity index 99% rename from src/main/java/ru/touchin/roboswag/components/observables/ui/UiBindable.java rename to src/main/java/ru/touchin/roboswag/components/utils/LifecycleBindable.java index eab334c..2a4157a 100644 --- a/src/main/java/ru/touchin/roboswag/components/observables/ui/UiBindable.java +++ b/src/main/java/ru/touchin/roboswag/components/utils/LifecycleBindable.java @@ -17,7 +17,7 @@ * */ -package ru.touchin.roboswag.components.observables.ui; +package ru.touchin.roboswag.components.utils; import android.support.annotation.NonNull; @@ -36,7 +36,7 @@ import rx.functions.Func1; * Use {@link #untilStop(Observable)} method to subscribe to observable where you want and unsubscribe onStop. * Use {@link #untilDestroy(Observable)} method to subscribe to observable where you want and unsubscribe onDestroy. */ -public interface UiBindable { +public interface LifecycleBindable { /** * Method should be used to subscribe to observable while this element is in started state.