简体   繁体   English

什么是SortedList <T> 使用RecyclerView.Adapter?

[英]What is the SortedList<T> working with RecyclerView.Adapter?

Android Support Library 22.1 was released yesterday. Android支持库22.1已于昨天发布。 Many new features were added into the v4 support library and v7, among which android.support.v7.util.SortedList<T> draws my attention. v4支持库和v7中添加了许多新功能,其中android.support.v7.util.SortedList<T>引起了我的注意。

It's said that, SortedList is a new data structure, works with RecyclerView.Adapter , maintains the item added/deleted/moved/changed animations provided by RecyclerView . 据说, SortedList是一个新的数据结构,工作原理RecyclerView.Adapter ,维护项目添加/删除/移动/改变所提供的动画RecyclerView It sounds like a List<T> in a ListView but seems more advanced and powerful. 听起来像ListViewList<T> ,但似乎更高级,更强大。

So, what is the difference between SortedList<T> and List<T> ? 那么, SortedList<T>List<T>什么区别? How could I use it efficiently? 如何有效使用它? What's the enforcement of SortedList<T> over List<T> if it is so? 如果是这样,那么对List<T>SortedList<T>的强制执行是什么? Could somebody post some samples of it? 有人可以张贴一些样品吗?

Any tips or codes will be appreciated. 任何提示或代码将不胜感激。 Thanks in advance. 提前致谢。

SortedList handles the communication to the Recycler adapter via Callback . SortedList通过Callback处理与Recycler适配器的通信。

One difference between SortedList and List is seen in the addAll helper method in the sample below. 在下面的示例的addAll帮助器方法中可以看到SortedListList之间的区别。

public void addAll(List<Page> items) {
        mPages.beginBatchedUpdates();
        for (Page item : items) {
            mPages.add(item);
        }
        mPages.endBatchedUpdates();
    }
  1. Keeps last added item 保留最后添加的项目

Say I have 10 cached items to load immediately when my recycler list is populated. 假设在填充回收商列表时,我有10个缓存项目要立即加载。 At the same time, I query my network for the same 10 items because they could have changed since I cached them. 同时,我在网络中查询相同的10个项目,因为自从将它们缓存以来,它们可能已经更改。 I can call the same addAll method and SortedList will replace the cachedItems with fetchedItems under the hood (always keeps the last added item). 我可以调用相同addAll方法和SortedList将取代在引擎盖下与fetchedItems的cachedItems(始终保持最后添加的项目)。

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

In a regular List , I would have duplicates of all my items (list size of 20). 在常规List ,我将拥有所有项目的副本(列表大小为20)。 With SortedList its replaces items that are the same using the Callback's areItemsTheSame . 使用SortedList它使用Callback的areItemsTheSame替换相同的areItemsTheSame

  1. Its smart about when to update the Views 何时更新视图很聪明

When the fetchedItems are added, onChange will only be called if one or more of the Page 's title changed. 添加fetchedItems时,仅当Page标题中的一个或多个更改时,才会调用onChange You can customize what SortedList looks for in the Callback's areContentsTheSame . 您可以自定义SortedList在回调的areContentsTheSame查找的areContentsTheSame

  1. Its performant 其表现

If you are going to add multiple items to a SortedList, BatchedCallback call convert individual onInserted(index, 1) calls into one onInserted(index, N) if items are added into consecutive indices. 如果你要多个项目添加到排序列表,BatchedCallback调用转换个别onInserted(指数1)呼叫到一个onInserted(索引,N),如果项目被加入到连续的指数。 This change can help RecyclerView resolve changes much more easily. 这种变化可以帮助解决RecyclerView变化更容易。

Sample 样品

You can have a getter on your adapter for your SortedList , but I just decided to add helper methods to my adapter. 您可以在适配器上为SortedList设置一个吸气剂,但是我只是决定向适配器添加辅助方法。

Adapter Class: 适配器类别:

  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();
    }
}

Page class: 页面类:

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:

<?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 class: 观看者类别:

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


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

SortedList is in v7 support library . v7 support library SortedList

A SortedList implementation that can keep items in order and also notify for changes in the list such that it can be bound to a RecyclerView.Adapter . 一个SortedList实现,它可以使项目保持顺序,并通知列表中的更改,以便可以将其绑定到RecyclerView.Adapter

It keeps items ordered using the compare(Object, Object) method and uses binary search to retrieve items. 它使用compare(Object, Object)方法使项目保持有序compare(Object, Object)并使用二进制搜索来检索项目。 If the sorting criteria of your items may change, make sure you call appropriate methods while editing them to avoid data inconsistencies. 如果项目的排序标准可能会更改,请确保在编辑它们时调用适当的方法,以避免数据不一致。

You can control the order of items and change notifications via the SortedList.Callback parameter. 您可以通过SortedList.Callback参数控制项目的顺序并更改通知。

Here below is a sample of use of SortedList , I think it is what you want, take a look at it and enjoy! 下面是使用SortedList的示例,我认为这是您想要的,看看并享受吧!

public class SortedListActivity extends ActionBarActivity {
    private RecyclerView mRecyclerView;
    private LinearLayoutManager mLinearLayoutManager;
    private SortedListAdapter mAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sorted_list_activity);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setHasFixedSize(true);
        mLinearLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLinearLayoutManager);
        mAdapter = new SortedListAdapter(getLayoutInflater(),
                new Item("buy milk"), new Item("wash the car"),
                new Item("wash the dishes"));
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setHasFixedSize(true);
        final EditText newItemTextView = (EditText) findViewById(R.id.new_item_text_view);
        newItemTextView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
                if (id == EditorInfo.IME_ACTION_DONE &&
                        (keyEvent == null || keyEvent.getAction() == KeyEvent.ACTION_DOWN)) {
                    final String text = textView.getText().toString().trim();
                    if (text.length() > 0) {
                        mAdapter.addItem(new Item(text));
                    }
                    textView.setText("");
                    return true;
                }
                return false;
            }
        });
    }

    private static class SortedListAdapter extends RecyclerView.Adapter<TodoViewHolder> {
        SortedList<Item> mData;
        final LayoutInflater mLayoutInflater;
        public SortedListAdapter(LayoutInflater layoutInflater, Item... items) {
            mLayoutInflater = layoutInflater;
            mData = new SortedList<Item>(Item.class, new SortedListAdapterCallback<Item>(this) {
                @Override
                public int compare(Item t0, Item t1) {
                    if (t0.mIsDone != t1.mIsDone) {
                        return t0.mIsDone ? 1 : -1;
                    }
                    int txtComp = t0.mText.compareTo(t1.mText);
                    if (txtComp != 0) {
                        return txtComp;
                    }
                    if (t0.id < t1.id) {
                        return -1;
                    } else if (t0.id > t1.id) {
                        return 1;
                    }
                    return 0;
                }

                @Override
                public boolean areContentsTheSame(Item oldItem,
                        Item newItem) {
                    return oldItem.mText.equals(newItem.mText);
                }

                @Override
                public boolean areItemsTheSame(Item item1, Item item2) {
                    return item1.id == item2.id;
                }
            });
            for (Item item : items) {
                mData.add(item);
            }
        }

        public void addItem(Item item) {
            mData.add(item);
        }

        @Override
        public TodoViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
            return new TodoViewHolder (
                    mLayoutInflater.inflate(R.layout.sorted_list_item_view, parent, false)) {
                @Override
                void onDoneChanged(boolean isDone) {
                    int adapterPosition = getAdapterPosition();
                    if (adapterPosition == RecyclerView.NO_POSITION) {
                        return;
                    }
                    mBoundItem.mIsDone = isDone;
                    mData.recalculatePositionOfItemAt(adapterPosition);
                }
            };
        }

        @Override
        public void onBindViewHolder(TodoViewHolder holder, int position) {
            holder.bindTo(mData.get(position));
        }

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

    abstract private static class TodoViewHolder extends RecyclerView.ViewHolder {
        final CheckBox mCheckBox;
        Item mBoundItem;
        public TodoViewHolder(View itemView) {
            super(itemView);
            mCheckBox = (CheckBox) itemView;
            mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (mBoundItem != null && isChecked != mBoundItem.mIsDone) {
                        onDoneChanged(isChecked);
                    }
                }
            });
        }

        public void bindTo(Item item) {
            mBoundItem = item;
            mCheckBox.setText(item.mText);
            mCheckBox.setChecked(item.mIsDone);
        }

        abstract void onDoneChanged(boolean isChecked);
    }

    private static class Item {
        String mText;
        boolean mIsDone = false;
        final public int id;
        private static int idCounter = 0;

        public Item(String text) {
            id = idCounter ++;
            this.mText = text;
        }
    }
}

There is a sample SortedListActivity in the support library source repository which demonstrates how to use SortedList and SortedListAdapterCallback inside a RecyclerView.Adapter. 支持库源存储库中有一个示例SortedListActivity,该示例演示了如何在RecyclerView.Adapter中使用SortedList和SortedListAdapterCallback。 From the root of the SDK, with the support library installed, it should be at extras/android/support/samples/Support7Demos/src/com/example/android/supportv7/util/SortedListActivity.java (also on github ). 从SDK的根目录开始,安装了支持库后,它应该位于extras/android/support/samples/Support7Demos/src/com/example/android/supportv7/util/SortedListActivity.java (也在github上 )。

The existence of these particular samples is mentioned exactly once in Google's documentation, at the bottom of a page dealing with a different topic, so I don't blame you for not finding it. 这些特殊示例的存在在Google文档的处理不同主题的页面的底部被提及一次 ,因此,我不怪您没有找到它。

About SortedList implementation, it is backed by an array of <T> with a default min capacity of 10 items. 关于SortedList实现,它由<T>数组支持,默认最小容量为10个项目。 Once the array is full the array is resized to size() + 10 阵列装满后,将其大小调整为size() + 10

The source code is available here 源代码在这里

From documentation 文档

A Sorted list implementation that can keep items in order and also notify for changes in the list such that it can be bound to a RecyclerView.Adapter. Sorted list实现,可以使项目保持顺序,并通知列表中的更改,以便可以将其绑定到RecyclerView.Adapter。

It keeps items ordered using the compare(Object, Object) method and uses binary search to retrieve items. 它使用compare(Object,Object)方法使项目保持有序,并使用二进制搜索来检索项目。 If the sorting criteria of your items may change, make sure you call appropriate methods while editing them to avoid data inconsistencies. 如果项目的排序标准可能会更改,请确保在编辑它们时调用适当的方法,以避免数据不一致。

You can control the order of items and change notifications via the SortedList.Callback parameter. 您可以通过SortedList.Callback参数控制项目的顺序并更改通知。

Regarding to performance they also added SortedList.BatchedCallback to carry out multiple operation at once instead of one at the time 关于性能,他们还添加了SortedList.BatchedCallback一次执行多个操作,而不是一次执行

A callback implementation that can batch notify events dispatched by the SortedList. 可以批量通知SortedList调度的事件的回调实现。

This class can be useful if you want to do multiple operations on a SortedList but don't want to dispatch each event one by one, which may result in a performance issue. 如果您要对SortedList进行多个操作,但又不想一个一个地分派每个事件,则这可能会导致性能问题,该类很有用。

For example, if you are going to add multiple items to a SortedList, BatchedCallback call convert individual onInserted(index, 1) calls into one onInserted(index, N) if items are added into consecutive indices. 例如,如果要将多个项目添加到SortedList,则将项目添加到连续索引中时,BatchedCallback调用将单个onInserted(index,1)调用转换为一个onInserted(index,N)。 This change can help RecyclerView resolve changes much more easily. 这种变化可以帮助解决RecyclerView变化更容易。

If consecutive changes in the SortedList are not suitable for batching, BatchingCallback dispatches them as soon as such case is detected. 如果SortedList中的连续更改不适合进行批处理,则在检测到这种情况后,BatchingCallback会立即分派它们。 After your edits on the SortedList is complete, you must always call dispatchLastEvent() to flush all changes to the Callback. 在SortedList上的编辑完成后,必须始终调用dispatchLastEvent()来刷新对回调的所有更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android RecyclerView.Adapter onCreateViewHolder()正在运行 - Android RecyclerView.Adapter onCreateViewHolder() working RecyclerView.Adapter getRef(position).getKey() 不工作 - RecyclerView.Adapter getRef(position).getKey() not working RecyclerView.Adapter中的按钮无法正常工作 - Button within RecyclerView.Adapter not working properly arrayadapter和recyclerview.adapter有什么区别? - What is the difference between arrayadapter and recyclerview.adapter? 扩展 Recyclerview.Adapter 与 RecyclerView.Adapter 有什么区别<subclassrecyclerviewadapter.viewholder>在回收站视图中</subclassrecyclerviewadapter.viewholder> - what is the difference between extends Recyclerview.Adapter vs RecyclerView.Adapter<SubclassRecyclerViewAdapter.ViewHolder> in RecyclerView RecyclerView.Adapter onClick - RecyclerView.Adapter onClick 什么是 RecyclerView.Adapter<MyAdapter.MyViewHolder> 以及它与 Android 中的 RecyclerView.Adapter 有何不同? - What is RecyclerView.Adapter<MyAdapter.MyViewHolder> and how it is different from RecyclerView.Adapter in Android? 更新RecyclerView.Adapter - Update RecyclerView.Adapter RecyclerView.Adapter的上下文 - Context for RecyclerView.Adapter 在什么情况下不调用RecyclerView.Adapter中的onBindViewHolder()? - What are the circumstances under which onBindViewHolder() in RecyclerView.Adapter is not called?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM