2015-07-09 9 views
12

L'associazione dati Android fornisce diverse interfacce dati osservabili, tra cui ObservableList. Ma SortedList (introdotto nella recente versione della libreria RecyclerView) non estende affatto l'Elenco.Come utilizzare SortedList in RecyclerView con la libreria di associazione dati Android?

Come è possibile utilizzare SortedList per RecyclerView con libreria di associazione dati Android?

+0

Questo non funziona per voi? https://github.com/radzio/android-data-binding-recyclerview –

+0

@ Jürgen'Kashban'Wahlmann Ho già controllato quel progetto, ma sfortunatamente no. Così ho anche depositato un problema per l'auther: https://github.com/radzio/android-data-binding-recyclerview/issues/7 –

risposta

10

Ispirato da George monte, ho realizzato la mia versione di ObservableSortedList le funzionalità dal SortedList originale, tra cui: aggiornamento

  • Batch. Basta chiamare beginBatchedUpdates() e endBatchedUpdates() a SortedList.
  • De-dup e aggiornamento intelligente. Il callback nel costruttore è responsabile per l'ordinazione, la deduplicazione e la differenziazione del contenuto.

codice completo:

public class ObservableSortedList<T> extends AbstractList<T> implements ObservableList<T> { 

    /** @see android.support.v7.util.SortedList.Callback */ 
    public interface Callback<T2> { 
    /** @see android.support.v7.util.SortedList.Callback#compare(Object, Object) */ 
    int compare(T2 o1, T2 o2); 
    /** @see android.support.v7.util.SortedList.Callback#areItemsTheSame(Object, Object) */ 
    boolean areItemsTheSame(T2 item1, T2 item2); 
    /** @see android.support.v7.util.SortedList.Callback#areContentsTheSame(Object, Object) */ 
    boolean areContentsTheSame(T2 oldItem, T2 newItem); 
    } 

    public ObservableSortedList(final Class<T> klass, final Callback<T> callback) { 
    mList = new SortedList<>(klass, new CallbackWrapper<>(callback)); 
    } 

    /** @see SortedList#beginBatchedUpdates() */ 
    public void beginBatchedUpdates() { mList.beginBatchedUpdates(); } 
    /** @see SortedList#endBatchedUpdates() */ 
    public void endBatchedUpdates() { mList.endBatchedUpdates(); } 

    @Override public boolean add(final T item) { 
    sTlsUpdated.set(false); 
    mList.add(item); 
    return sTlsUpdated.get(); // May be set by Callback.onInserted() or onChanged(). 
    } 

    @Override public T set(final int location, final T object) { 
    final T old = mList.get(location); 
    mList.updateItemAt(location, cast(object)); 
    return old; 
    } 

    @Override public int indexOf(final Object object) { 
    try { 
     return mList.indexOf(cast(object)); 
    } catch (final ClassCastException ignored) { 
     return -1; 
    } 
    } 

    @Override public boolean remove(final Object object) { 
    try { 
     return mList.remove(cast(object)); 
    } catch (final ClassCastException ignored) { 
     return false; 
    } 
    } 

    @SuppressWarnings("unchecked") private T cast(final Object object) { return (T) object; } 

    @Override public boolean contains(final Object object) { return indexOf(object) != SortedList.INVALID_POSITION; } 
    @Override public T get(final int location) { return mList.get(location); } 
    @Override public int size() { return mList.size(); } 
    @Override public void clear() { mList.clear(); } 
    @Override public T remove(final int location) { return mList.removeItemAt(location); } 

    /* ObservableList */ 

    @Override public void addOnListChangedCallback(final OnListChangedCallback<? extends ObservableList<T>> callback) { 
    if (mListeners == null) this.mListeners = new ListChangeRegistry(); 
    mListeners.add(callback); 
    } 

    @Override public void removeOnListChangedCallback(final OnListChangedCallback<? extends ObservableList<T>> callback) { 
    if (mListeners == null) return; 
    mListeners.remove(callback); 
    } 

    private final SortedList<T> mList; 
    private static final ThreadLocal<Boolean> sTlsUpdated = new ThreadLocal<>(); 
    private transient @Nullable ListChangeRegistry mListeners = new ListChangeRegistry(); 

    public class CallbackWrapper<T2> extends SortedList.Callback<T2> { 

    @Override public final void onInserted(final int position, final int count) { 
     sTlsUpdated.set(true); 
     if (mListeners != null) mListeners.notifyInserted(ObservableSortedList.this, position, count); 
    } 

    @Override public final void onRemoved(final int position, final int count) { 
     if (mListeners != null) mListeners.notifyRemoved(ObservableSortedList.this, position, count); 
    } 

    @Override public final void onMoved(final int fromPosition, final int toPosition) { 
     if (mListeners != null) mListeners.notifyMoved(ObservableSortedList.this, fromPosition, toPosition, 1); 
    } 

    @Override public final void onChanged(final int position, final int count) { 
     sTlsUpdated.set(true); 
     if (mListeners != null) mListeners.notifyChanged(ObservableSortedList.this, position, count); 
    } 

    @Override public int compare(final T2 o1, final T2 o2) { return mCallback.compare(o1, o2); } 
    @Override public boolean areContentsTheSame(final T2 oldItem, final T2 newItem) { return mCallback.areContentsTheSame(oldItem, newItem); } 
    @Override public boolean areItemsTheSame(final T2 item1, final T2 item2) { return mCallback.areItemsTheSame(item1, item2); } 
    public CallbackWrapper(final Callback<T2> callback) { mCallback = callback; } 

    private final Callback<T2> mCallback; 
    } 
} 
8

Per rendere un supporto SortedList Observability in associazione dati, è necessario implementare l'interfaccia da soli. Poiché c'è un conflitto nell'API, sembra che dovrai completarlo. Qualcosa di simile a questo:

public class ObservableSortedList<T> implements ObservableList<T> { 
    private final SortedList<T> mList; 
    private final ListChangeRegistry mListeners = new ListChangeRegistry(); 

    @Override 
    public boolean add(T item) { 
     int index = mList.add(item); 
     mListeners.notifyInserted(this, index, 1); 
    } 

    @Observable 
    public void addOnListChangedCallback(OnListChangedCallback<? extends ObservableList<T>> callback) { 
     mListeners.add(callback); 
    } 

    ... 
} 
+1

In questo modo, devo rinunciare a molti vantaggi di usare SortedList direttamente, come aggiornamento batch, duplicazione, aggiornamento intelligente (evitare aggiornamento aggiornamento contenuto invariato). Penso che non sia il modo ottimale. –

+0

È ancora possibile averli, ma accedervi tramite metodi che non hanno firme in conflitto. Ad esempio, add (T) restituisce un int in SortedList e boolean in List. Ci vorrà solo un piccolo sforzo, ma sarai comunque in grado di ottenere tutti i vantaggi di SortedList. –

+0

@GeorgeMount ci sono piani per risolvere questo problema? un po 'sciocco che non possiamo usare 'SortedList' fuori dalla scatola con il databinding, per non parlare della parcellizzazione di' SortedList' – ZakTaccardi

Problemi correlati