blob: ea574b8b0c2f777de67b6dd52733cf91bdda72b4 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.baku.toolkit.bind;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import lombok.Getter;
import lombok.experimental.Accessors;
import lombok.experimental.Delegate;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
@Accessors(prefix = "m")
public class RxRecyclerAdapter<T, VH extends ViewHolder>
extends RecyclerView.Adapter<RxRecyclerAdapter.ViewHolderAdapter<VH>>
implements RangeAdapter, ListAccumulator<T> {
public static class ViewHolderAdapter<B extends ViewHolder> extends RecyclerView.ViewHolder {
public final B bakuViewHolder;
public ViewHolderAdapter(final B vh) {
super(vh.getView());
bakuViewHolder = vh;
}
}
private final ViewAdapter<? super T, VH> mViewAdapter;
/**
* The main purpose of this class is to capture the generic arg {@link T}. Otherwise, the
* {@link Delegate} annotation fails to capture it and cannot implement {@link ListAccumulator}
* with the right generic type.
* <p>
* While we're here, we might as well use it to override
* {@link android.support.v7.widget.RecyclerView.Adapter#getItemId(int)}.
*/
private abstract class Delegated implements ListAccumulator<T> {
/**
* Overrides {@link android.support.v7.widget.RecyclerView.Adapter#getItemId(int)}.
*/
public abstract long getItemId(int position);
}
@Delegate(types = Delegated.class)
private ListDeltaAccumulator<T> mLatestState =
new DerivedListDeltaAccumulator<>(null, ListAccumulators.empty());
@Getter
private final Subscription mSubscription;
public RxRecyclerAdapter(final Observable<? extends ListDeltaAccumulator<T>> data,
final ViewAdapter<? super T, VH> viewAdapter,
final Action1<Throwable> onError) {
setHasStableIds(true);
mViewAdapter = viewAdapter;
mSubscription = data
.observeOn(AndroidSchedulers.mainThread())
.subscribe(d -> {
mLatestState = d;
d.notifyDeltas(this);
}, onError);
}
@Override
public void close() throws Exception {
mSubscription.unsubscribe();
}
@Override
public ViewHolderAdapter<VH> onCreateViewHolder(final ViewGroup parent, final int viewType) {
return new ViewHolderAdapter<>(
mViewAdapter.createViewHolder(mViewAdapter.createView(parent)));
}
@Override
public void onBindViewHolder(final ViewHolderAdapter<VH> holder, final int position) {
mViewAdapter.bindViewHolder(
holder.bakuViewHolder, position, mLatestState.getRowAt(position));
}
@Override
public int getItemCount() {
return getCount();
}
}