summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2018-01-06 03:58:43 -0600
committerSamuel Holland <samuel@sholland.org>2018-01-06 04:09:30 -0600
commitc73287f64bc575672aed325cc029b26b1cf72202 (patch)
tree4a6f4c4e930f944bcaf0222e9b66f79352967e80 /app
parente24654ce7ceaa9a319421b420ea1a97c1b6058e4 (diff)
databinding: Add an adapter for the KeyedObservableList
This adapter actually finally implements stable IDs correctly. Signed-off-by: Samuel Holland <samuel@sholland.org>
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/com/wireguard/android/databinding/KeyedObservableListAdapter.java127
1 files changed, 127 insertions, 0 deletions
diff --git a/app/src/main/java/com/wireguard/android/databinding/KeyedObservableListAdapter.java b/app/src/main/java/com/wireguard/android/databinding/KeyedObservableListAdapter.java
new file mode 100644
index 00000000..d1d377aa
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/databinding/KeyedObservableListAdapter.java
@@ -0,0 +1,127 @@
+package com.wireguard.android.databinding;
+
+import android.content.Context;
+import android.databinding.DataBindingUtil;
+import android.databinding.ObservableList;
+import android.databinding.ViewDataBinding;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import com.wireguard.android.BR;
+import com.wireguard.android.util.Keyed;
+import com.wireguard.android.util.KeyedObservableList;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * A generic {@code ListAdapter} backed by a {@code KeyedObservableList}.
+ */
+
+class KeyedObservableListAdapter<K, E extends Keyed<? extends K>> extends BaseAdapter {
+ private final OnListChangedCallback<E> callback = new OnListChangedCallback<>(this);
+ private final int layoutId;
+ private final LayoutInflater layoutInflater;
+ private KeyedObservableList<K, E> list;
+
+ KeyedObservableListAdapter(final Context context, final int layoutId,
+ final KeyedObservableList<K, E> list) {
+ this.layoutId = layoutId;
+ layoutInflater = LayoutInflater.from(context);
+ setList(list);
+ }
+
+ @Override
+ public int getCount() {
+ return list != null ? list.size() : 0;
+ }
+
+ @Override
+ public E getItem(final int position) {
+ if (list == null || position < 0 || position >= list.size())
+ return null;
+ return list.get(position);
+ }
+
+ @Override
+ public long getItemId(final int position) {
+ final K key = getKey(position);
+ return key != null ? key.hashCode() : -1;
+ }
+
+ private K getKey(final int position) {
+ final E item = getItem(position);
+ return item != null ? item.getKey() : null;
+ }
+
+ @Override
+ public View getView(final int position, final View convertView, final ViewGroup parent) {
+ ViewDataBinding binding = DataBindingUtil.getBinding(convertView);
+ if (binding == null)
+ binding = DataBindingUtil.inflate(layoutInflater, layoutId, parent, false);
+ binding.setVariable(BR.collection, list);
+ binding.setVariable(BR.key, getKey(position));
+ binding.setVariable(BR.item, getItem(position));
+ binding.executePendingBindings();
+ return binding.getRoot();
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ void setList(final KeyedObservableList<K, E> newList) {
+ if (list != null)
+ list.removeOnListChangedCallback(callback);
+ list = newList;
+ if (list != null) {
+ list.addOnListChangedCallback(callback);
+ }
+ notifyDataSetChanged();
+ }
+
+ private static final class OnListChangedCallback<E extends Keyed<?>>
+ extends ObservableList.OnListChangedCallback<ObservableList<E>> {
+
+ private final WeakReference<KeyedObservableListAdapter<?, E>> weakAdapter;
+
+ private OnListChangedCallback(final KeyedObservableListAdapter<?, E> adapter) {
+ weakAdapter = new WeakReference<>(adapter);
+ }
+
+ @Override
+ public void onChanged(final ObservableList<E> sender) {
+ final KeyedObservableListAdapter 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);
+ }
+ }
+}