lists interface a bit changed
This commit is contained in:
parent
0ff35b0f60
commit
582c7ff9dd
14
build.gradle
14
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'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Boolean> attachedToWindowSubject = BehaviorSubject.create();
|
||||
private final Observable<Boolean> 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 <T> Subscription bind(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
final Observable<T> 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 <T> Subscription untilStop(@NonNull final Observable<T> observable) {
|
||||
return baseLifecycleBindable.untilStop(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction) {
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction,
|
||||
@NonNull final Action0 onCompletedAction) {
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable) {
|
||||
return baseLifecycleBindable.untilDestroy(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction) {
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction,
|
||||
@NonNull final Action0 onCompletedAction) {
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<TItem, TViewHolder extends ObservableCollectionAdapter.ViewHolder>
|
||||
extends RecyclerView.Adapter<BindableViewHolder> {
|
||||
|
||||
private static final int PRE_LOADING_COUNT = 10;
|
||||
|
||||
private static final int LIST_ITEM_TYPE = 12313212;
|
||||
|
||||
@NonNull
|
||||
private final BehaviorSubject<ObservableCollection<TItem>> observableCollectionSubject
|
||||
= BehaviorSubject.create((ObservableCollection<TItem>) null);
|
||||
@NonNull
|
||||
private final LifecycleBindable lifecycleBindable;
|
||||
@Nullable
|
||||
private OnItemClickListener<TItem> onItemClickListener;
|
||||
private int lastUpdatedChangeNumber = -1;
|
||||
@NonNull
|
||||
private final Observable<?> historyPreLoadingObservable;
|
||||
|
||||
@NonNull
|
||||
private final ObservableList<TItem> innerCollection = new ObservableList<>();
|
||||
private boolean anyChangeApplied;
|
||||
@NonNull
|
||||
private final List<RecyclerView> 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<TItem> 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<TItem> items) {
|
||||
setObservableCollection(new ObservableList<>(items));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ObservableCollection<TItem> getObservableCollection() {
|
||||
return observableCollectionSubject.getValue();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Observable<ObservableCollection<TItem>> 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<TItem> 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<TItem> 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<Change<TItem>> 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<TItem> 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<TItem> {
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<TActivity extends ViewControllerActivity<?>,
|
||||
TFragment extends ViewControllerFragment<?, TActivity>>
|
||||
implements UiBindable {
|
||||
implements LifecycleBindable {
|
||||
|
||||
@NonNull
|
||||
private final TActivity activity;
|
||||
|
|
@ -58,13 +58,12 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
@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<TActivity extends ViewControllerActivity<?>,
|
|||
*/
|
||||
@CallSuper
|
||||
public void onCreate() {
|
||||
baseUiBindable.onCreate();
|
||||
baseLifecycleBindable.onCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -156,7 +155,7 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
*/
|
||||
@CallSuper
|
||||
public void onStart() {
|
||||
baseUiBindable.onStart();
|
||||
baseLifecycleBindable.onStart();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -175,7 +174,7 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
*/
|
||||
@CallSuper
|
||||
public void onStop() {
|
||||
baseUiBindable.onStop();
|
||||
baseLifecycleBindable.onStop();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -184,7 +183,7 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
*/
|
||||
@CallSuper
|
||||
public void onDestroy() {
|
||||
baseUiBindable.onDestroy();
|
||||
baseLifecycleBindable.onDestroy();
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
|
|
@ -199,23 +198,23 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
}
|
||||
|
||||
@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 <T> Subscription bind(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.bind(observable, onNextAction);
|
||||
return baseLifecycleBindable.bind(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable) {
|
||||
return baseUiBindable.untilStop(observable);
|
||||
return baseLifecycleBindable.untilStop(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.untilStop(observable, onNextAction);
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -223,7 +222,7 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
public <T> Subscription untilStop(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction) {
|
||||
return baseUiBindable.untilStop(observable, onNextAction, onErrorAction);
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -232,19 +231,19 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction,
|
||||
@NonNull final Action0 onCompletedAction) {
|
||||
return baseUiBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable) {
|
||||
return baseUiBindable.untilDestroy(observable);
|
||||
return baseLifecycleBindable.untilDestroy(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.untilDestroy(observable, onNextAction);
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -252,7 +251,7 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction) {
|
||||
return baseUiBindable.untilDestroy(observable, onNextAction, onErrorAction);
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction, onErrorAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -261,11 +260,11 @@ public class ViewController<TActivity extends ViewControllerActivity<?>,
|
|||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> 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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<OnBackPressedListener> 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 <T> Subscription bind(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.bind(observable, onNextAction);
|
||||
return baseLifecycleBindable.bind(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -158,7 +158,7 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||
public <T> Subscription untilStop(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> 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<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> onErrorAction,
|
||||
@NonNull final Action0 onCompletedAction) {
|
||||
return baseUiBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction, onErrorAction, onCompletedAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable) {
|
||||
return baseUiBindable.untilStop(observable);
|
||||
return baseLifecycleBindable.untilStop(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilStop(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.untilStop(observable, onNextAction);
|
||||
return baseLifecycleBindable.untilStop(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable) {
|
||||
return baseUiBindable.untilDestroy(observable);
|
||||
return baseLifecycleBindable.untilDestroy(observable);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable, @NonNull final Action1<T> onNextAction) {
|
||||
return baseUiBindable.untilDestroy(observable, onNextAction);
|
||||
return baseLifecycleBindable.untilDestroy(observable, onNextAction);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -199,7 +199,7 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||
public <T> Subscription untilDestroy(@NonNull final Observable<T> observable,
|
||||
@NonNull final Action1<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> 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<T> onNextAction,
|
||||
@NonNull final Action1<Throwable> 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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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<Boolean> 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<Throwable> 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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
Loading…
Reference in New Issue