diff options
author | Samuel Holland <samuel@sholland.org> | 2018-01-06 03:58:43 -0600 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2018-01-06 04:09:30 -0600 |
commit | c73287f64bc575672aed325cc029b26b1cf72202 (patch) | |
tree | 4a6f4c4e930f944bcaf0222e9b66f79352967e80 | |
parent | e24654ce7ceaa9a319421b420ea1a97c1b6058e4 (diff) |
databinding: Add an adapter for the KeyedObservableList
This adapter actually finally implements stable IDs correctly.
Signed-off-by: Samuel Holland <samuel@sholland.org>
-rw-r--r-- | app/src/main/java/com/wireguard/android/databinding/KeyedObservableListAdapter.java | 127 |
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); + } + } +} |