2018-07-05 21:34:50 +02:00
|
|
|
/*
|
2019-01-02 01:57:15 +01:00
|
|
|
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
|
2018-07-06 04:09:48 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2018-07-05 21:34:50 +02:00
|
|
|
*/
|
|
|
|
|
2018-07-04 23:47:55 +02:00
|
|
|
package com.wireguard.android.databinding;
|
|
|
|
|
|
|
|
import android.content.Context;
|
2018-12-18 11:45:37 +01:00
|
|
|
import androidx.databinding.DataBindingUtil;
|
|
|
|
import androidx.databinding.ObservableList;
|
|
|
|
import androidx.databinding.ViewDataBinding;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
2018-07-04 23:47:55 +02:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
|
|
|
import com.wireguard.android.BR;
|
|
|
|
import com.wireguard.android.util.ObservableKeyedList;
|
|
|
|
import com.wireguard.util.Keyed;
|
|
|
|
|
|
|
|
import java.lang.ref.WeakReference;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A generic {@code RecyclerView.Adapter} backed by a {@code ObservableKeyedList}.
|
|
|
|
*/
|
|
|
|
|
2018-07-06 23:02:48 +02:00
|
|
|
public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>> extends Adapter<ObservableKeyedRecyclerViewAdapter.ViewHolder> {
|
2018-07-04 23:47:55 +02:00
|
|
|
|
|
|
|
private final OnListChangedCallback<E> callback = new OnListChangedCallback<>(this);
|
|
|
|
private final int layoutId;
|
|
|
|
private final LayoutInflater layoutInflater;
|
2018-07-13 02:10:35 +02:00
|
|
|
@Nullable private ObservableKeyedList<K, E> list;
|
|
|
|
@Nullable private RowConfigurationHandler rowConfigurationHandler;
|
2018-07-04 23:47:55 +02:00
|
|
|
|
|
|
|
ObservableKeyedRecyclerViewAdapter(final Context context, final int layoutId,
|
|
|
|
final ObservableKeyedList<K, E> list) {
|
|
|
|
this.layoutId = layoutId;
|
|
|
|
layoutInflater = LayoutInflater.from(context);
|
|
|
|
setList(list);
|
|
|
|
}
|
|
|
|
|
2018-07-13 02:10:35 +02:00
|
|
|
@Nullable
|
2018-07-04 23:47:55 +02:00
|
|
|
private E getItem(final int position) {
|
|
|
|
if (list == null || position < 0 || position >= list.size())
|
|
|
|
return null;
|
|
|
|
return list.get(position);
|
|
|
|
}
|
|
|
|
|
2018-09-06 01:33:42 +02:00
|
|
|
@Override
|
|
|
|
public int getItemCount() {
|
|
|
|
return list != null ? list.size() : 0;
|
|
|
|
}
|
|
|
|
|
2018-07-04 23:47:55 +02:00
|
|
|
@Override
|
|
|
|
public long getItemId(final int position) {
|
|
|
|
final K key = getKey(position);
|
|
|
|
return key != null ? key.hashCode() : -1;
|
|
|
|
}
|
|
|
|
|
2018-07-13 02:10:35 +02:00
|
|
|
@Nullable
|
2018-07-04 23:47:55 +02:00
|
|
|
private K getKey(final int position) {
|
|
|
|
final E item = getItem(position);
|
|
|
|
return item != null ? item.getKey() : null;
|
|
|
|
}
|
|
|
|
|
2018-07-06 23:02:48 +02:00
|
|
|
@SuppressWarnings("unchecked")
|
2018-07-04 23:47:55 +02:00
|
|
|
@Override
|
2018-07-13 02:10:35 +02:00
|
|
|
public void onBindViewHolder(final ViewHolder holder, final int position) {
|
2018-07-04 23:47:55 +02:00
|
|
|
holder.binding.setVariable(BR.collection, list);
|
|
|
|
holder.binding.setVariable(BR.key, getKey(position));
|
|
|
|
holder.binding.setVariable(BR.item, getItem(position));
|
|
|
|
holder.binding.executePendingBindings();
|
2018-07-06 23:02:48 +02:00
|
|
|
|
|
|
|
if (rowConfigurationHandler != null) {
|
2018-09-06 03:17:14 +02:00
|
|
|
final E item = getItem(position);
|
2018-07-13 02:10:35 +02:00
|
|
|
if (item != null) {
|
|
|
|
rowConfigurationHandler.onConfigureRow(holder.binding, item, position);
|
|
|
|
}
|
2018-07-06 23:02:48 +02:00
|
|
|
}
|
2018-07-04 23:47:55 +02:00
|
|
|
}
|
|
|
|
|
2018-09-06 01:33:42 +02:00
|
|
|
@Override
|
|
|
|
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
|
|
|
|
return new ViewHolder(DataBindingUtil.inflate(layoutInflater, layoutId, parent, false));
|
|
|
|
}
|
|
|
|
|
2018-07-13 02:10:35 +02:00
|
|
|
void setList(@Nullable final ObservableKeyedList<K, E> newList) {
|
2018-07-04 23:47:55 +02:00
|
|
|
if (list != null)
|
|
|
|
list.removeOnListChangedCallback(callback);
|
|
|
|
list = newList;
|
|
|
|
if (list != null) {
|
|
|
|
list.addOnListChangedCallback(callback);
|
|
|
|
}
|
|
|
|
notifyDataSetChanged();
|
|
|
|
}
|
|
|
|
|
2018-07-06 23:02:48 +02:00
|
|
|
void setRowConfigurationHandler(final RowConfigurationHandler rowConfigurationHandler) {
|
|
|
|
this.rowConfigurationHandler = rowConfigurationHandler;
|
|
|
|
}
|
|
|
|
|
2018-09-06 01:33:42 +02:00
|
|
|
public interface RowConfigurationHandler<B extends ViewDataBinding, T> {
|
|
|
|
void onConfigureRow(B binding, T item, int position);
|
|
|
|
}
|
|
|
|
|
2018-07-04 23:47:55 +02:00
|
|
|
private static final class OnListChangedCallback<E extends Keyed<?>>
|
|
|
|
extends ObservableList.OnListChangedCallback<ObservableList<E>> {
|
|
|
|
|
|
|
|
private final WeakReference<ObservableKeyedRecyclerViewAdapter<?, E>> weakAdapter;
|
|
|
|
|
|
|
|
private OnListChangedCallback(final ObservableKeyedRecyclerViewAdapter<?, E> adapter) {
|
|
|
|
weakAdapter = new WeakReference<>(adapter);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onChanged(final ObservableList<E> sender) {
|
|
|
|
final ObservableKeyedRecyclerViewAdapter adapter = weakAdapter.get();
|
|
|
|
if (adapter != null)
|
|
|
|
adapter.notifyDataSetChanged();
|
|
|
|
else
|
|
|
|
sender.removeOnListChangedCallback(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onItemRangeChanged(final ObservableList<E> sender, final int positionStart,
|
|
|
|
final int itemCount) {
|
|
|
|
onChanged(sender);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onItemRangeInserted(final ObservableList<E> sender, final int positionStart,
|
|
|
|
final int itemCount) {
|
|
|
|
onChanged(sender);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onItemRangeMoved(final ObservableList<E> sender, final int fromPosition,
|
|
|
|
final int toPosition, final int itemCount) {
|
|
|
|
onChanged(sender);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onItemRangeRemoved(final ObservableList<E> sender, final int positionStart,
|
|
|
|
final int itemCount) {
|
|
|
|
onChanged(sender);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
|
|
final ViewDataBinding binding;
|
|
|
|
|
2018-07-05 21:34:50 +02:00
|
|
|
public ViewHolder(final ViewDataBinding binding) {
|
2018-07-04 23:47:55 +02:00
|
|
|
super(binding.getRoot());
|
|
|
|
|
|
|
|
this.binding = binding;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|