Что такое SortedList, работающий с RecyclerView.Переходник?


Библиотека Поддержки Android 22.1 был выпущен вчера. Многие новые функции были добавлены в библиотеку поддержки v4 и v7, среди которых android.support.v7.util.SortedList<T> привлекает мое внимание.

говорят, что SortedList новая структура данных, работает с RecyclerView.Adapter, поддерживает элемент добавлен / удален/перемещен / изменен анимации, предоставляемые RecyclerView. Это звучит как List<T> на ListView но, кажется, более продвинутый и мощный.

так, в чем разница между SortedList<T> и List<T>? Как я могу использовать его эффективно? Что такое принудительное исполнение SortedList<T> over List<T> если это так? Может кто-нибудь опубликовать некоторые образцы?

любые советы или коды будут оценены. Спасибо заранее.

4 68

4 ответа:

SortedList обрабатывает связь с адаптером рециркулятора через Callback.

одна разница между SortedList и List видел в addAll вспомогательный метод в примере ниже.

public void addAll(List<Page> items) {
        mPages.beginBatchedUpdates();
        for (Page item : items) {
            mPages.add(item);
        }
        mPages.endBatchedUpdates();
    }
  1. сохраняет последний добавленный элемент

скажем, у меня есть 10 кэшированных элементов для загрузки сразу же, когда мой список recycler заполняется. В то же время я запрашиваю свою сеть для тех же 10 элементов, потому что они могли измениться с тех пор, как я их кэшировал. Я можно назвать то же самое addAll способ и SortedList заменит cachedItems с fetchedItems под капотом (всегда сохраняет последний добавленный элемент).

// After creating adapter
myAdapter.addAll(cachedItems)
// Network callback
myAdapter.addAll(fetchedItems)

в обычном List, у меня были бы дубликаты всех моих элементов (размер списка 20). С SortedList его заменяет элементы, которые совпадают с помощью обратного вызова areItemsTheSame.

  1. его умный о том, когда обновить представления

когда fetchedItems добавляются,onChange будет вызывается, если один или несколько из Page's название изменилось. Вы можете настроить то, что SortedList ищет в обратном вызове areContentsTheSame.

  1. его производительным

если вы собираетесь добавить несколько элементов в SortedList, вызов BatchedCallback преобразует отдельные вызовы onInserted(index, 1) в один вызов onInserted(index, N), если элементы добавляются в последовательные индексы. Это изменение может помочь RecyclerView разрешить изменения гораздо больше легко.

пример

вы можете иметь геттер на вашем адаптере для вашего SortedList, но я просто решил добавить вспомогательные методы к своему адаптеру.

Класс Адаптера:

  public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private SortedList<Page> mPages;

    public MyAdapter() {
        mPages = new SortedList<Page>(Page.class, new SortedList.Callback<Page>() {
            @Override
            public int compare(Page o1, Page o2) {
                return o1.getTitle().compareTo(o2.getTitle());
            }

            @Override
            public void onInserted(int position, int count) {
                notifyItemRangeInserted(position, count);
            }

            @Override
            public void onRemoved(int position, int count) {
                notifyItemRangeRemoved(position, count);
            }

            @Override
            public void onMoved(int fromPosition, int toPosition) {
                notifyItemMoved(fromPosition, toPosition);
            }

            @Override
            public void onChanged(int position, int count) {
                notifyItemRangeChanged(position, count);
            }

            @Override
            public boolean areContentsTheSame(Page oldItem, Page newItem) {
                // return whether the items' visual representations are the same or not.
                return oldItem.getTitle().equals(newItem.getTitle());
            }

            @Override
            public boolean areItemsTheSame(Page item1, Page item2) {
                return item1.getId() == item2.getId();
            }
        });

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.viewholder_page, parent, false);
        return new PageViewHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        PageViewHolder pageViewHolder = (PageViewHolder) holder;
        Page page = mPages.get(position);
        pageViewHolder.textView.setText(page.getTitle());
    }

    @Override
    public int getItemCount() {
        return mPages.size();
    }

    // region PageList Helpers
    public Page get(int position) {
        return mPages.get(position);
    }

    public int add(Page item) {
        return mPages.add(item);
    }

    public int indexOf(Page item) {
        return mPages.indexOf(item);
    }

    public void updateItemAt(int index, Page item) {
        mPages.updateItemAt(index, item);
    }

    public void addAll(List<Page> items) {
        mPages.beginBatchedUpdates();
        for (Page item : items) {
            mPages.add(item);
        }
        mPages.endBatchedUpdates();
    }

    public void addAll(Page[] items) {
        addAll(Arrays.asList(items));
    }

    public boolean remove(Page item) {
        return mPages.remove(item);
    }

    public Page removeItemAt(int index) {
        return mPages.removeItemAt(index);
    }

    public void clear() {
       mPages.beginBatchedUpdates();
       //remove items at end, to avoid unnecessary array shifting
       while (mPages.size() > 0) {
          mPages.removeItemAt(mPages.size() - 1);
       }
       mPages.endBatchedUpdates();
    }
}

класс страницы:

public class Page {
    private String title;
    private long id;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}

Viewholder xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/text_view"
        style="@style/TextStyle.Primary.SingleLine"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

класса Viewholder:

public class PageViewHolder extends RecyclerView.ViewHolder {
    public TextView textView;


    public PageViewHolder(View itemView) {
        super(itemView);
        textView = (TextView)item.findViewById(R.id.text_view);
    }
}

SortedList находится в v7 support library.

A SortedList реализация, которая может содержать элементы в порядке, а также уведомлять об изменениях в списке таким образом, чтобы он мог быть привязан к RecyclerView.Adapter.

он сохраняет элементы, упорядоченные с помощью compare(Object, Object) метод и использует двоичный поиск для извлечения элементов. Если критерии сортировки вашего элементы могут меняться, убедитесь, что вы вызываете соответствующие методы во время редактирования чтобы избежать несогласованности данных.

вы можете контролировать порядок элементов и уведомления об изменениях через

в репозитории источника библиотеки поддержки есть пример SortedListActivity, который демонстрирует, как использовать SortedList и SortedListAdapterCallback внутри RecyclerView.Адаптер. Из корня SDK, с установленной библиотекой поддержки, он должен быть в extras/android/support/samples/Support7Demos/src/com/example/android/supportv7/util/SortedListActivity.java (на github).

существование этих конкретных образцов упоминается только один раз в документации Google, в нижней части страницы, посвященной другой теме, так что Я не виню тебя за то, что ты его не нашел.

о SortedList реализация, она поддерживается массивом <T> с минимальной емкостью по умолчанию 10 элементов. После заполнения массива размер массива изменяется на size() + 10

исходный код здесь

С документация

реализация отсортированного списка, которая может содержать элементы в порядке, а также уведомлять об изменениях в списке таким образом, чтобы он мог быть привязан к RecyclerView.Адаптер.

он сохраняет элементы, упорядоченные с помощью метода compare (Object, Object) и использует двоичный поиск для извлечения элементов. Если критерии сортировки вашего элементы могут меняться, убедитесь, что вы вызываете соответствующие методы во время редактирования чтобы избежать несогласованности данных.

вы можете контролировать порядок элементов и изменять уведомления с помощью Объекта sortedlist.Параметр обратного вызова.

относительно производительности они также добавили SortedList.BatchedCallback to выполняйте сразу несколько операций вместо одной за раз

реализация обратного вызова, которая может пакетно уведомлять события, отправленные сортированный список.

этот класс может быть полезна, если вы хотите сделать несколько операций на SortedList, но не хотите отправлять каждое событие по одному, что может в результате возникает проблема с производительностью.

например, если вы собираетесь добавить несколько элементов в список сортировки, Преобразование вызова BatchedCallback индивидуальные onInserted (индекс, 1) вызовы в один onInserted (индекс, N), если элементы добавляются в последовательный индексы. Это изменение может помочь RecyclerView разрешить изменения гораздо больше легко.

Если последовательные изменения в SortedList не подходят для дозирование, BatchingCallback отправляет их, как только такой случай обнаруженный. После редактирование объекта sortedlist, вы должны всегда вызывайте dispatchLastEvent (), чтобы сбросить все изменения обратного вызова.