SortedList는 무엇입니까 RecyclerView.Adapter로 작업합니까?
Android 지원 라이브러리 22.1 이 어제 출시되었습니다. 많은 새로운 기능이 v4 지원 라이브러리와 v7에 추가되었는데, 그 중 android.support.v7.util.SortedList<T>
주목을 끌었습니다.
그것의가 말했다, SortedList
새로운 데이터 구조와 작동 RecyclerView.Adapter
에 의해 제공 / 삭제 / 이동 / 변경 애니메이션을 추가 한 항목을 유지 관리합니다 RecyclerView
. 그것은 같은 소리 List<T>
A의 ListView
하지만 고급하고 강력한 보인다.
그래서, 차이 무엇 SortedList<T>
과 List<T>
? 어떻게 효율적으로 사용할 수 있습니까? 그렇다면 SortedList<T>
오버 의 집행은 무엇입니까 List<T>
? 누군가 샘플을 게시 할 수 있습니까?
모든 팁이나 코드를 주시면 감사하겠습니다. 미리 감사드립니다.
SortedList
를 통해 Recycler 어댑터와의 통신을 처리합니다 Callback
.
사이의 한 가지 차이점 SortedList
과는 List
에서 볼 수 addAll
아래의 예제에서 헬퍼 방법.
public void addAll(List<Page> items) {
mPages.beginBatchedUpdates();
for (Page item : items) {
mPages.add(item);
}
mPages.endBatchedUpdates();
}
- 마지막으로 추가 된 항목 유지
내 리사이클 러 목록이 채워지면 즉시로드 할 캐시 된 항목이 10 개 있다고 가정 해 보겠습니다. 동시에 캐시 한 이후 변경되었을 수 있으므로 동일한 10 개 항목에 대해 네트워크에 쿼리합니다. 동일한 addAll
메서드를 호출 할 수 SortedList
있으며 캐시 된 항목을 내부적으로 fetchedItems로 대체합니다 (항상 마지막으로 추가 된 항목을 유지함).
// After creating adapter
myAdapter.addAll(cachedItems)
// Network callback
myAdapter.addAll(fetchedItems)
일반에서는 List
모든 항목 (목록 크기 20)이 중복됩니다. 함께 SortedList
자사을 대체 항목이 콜백의를 사용하여 동일합니다 areItemsTheSame
.
- 뷰 업데이트시기에 대한 스마트
fetchedItems가 추가되면 의 제목 onChange
중 하나 이상이 Page
변경된 경우에만 호출됩니다 . 당신은 무엇을 사용자 정의 할 수 있습니다 SortedList
콜백의에서 찾습니다 areContentsTheSame
.
- 성능
SortedList에 여러 항목을 추가하려는 경우 BatchedCallback 호출은 항목이 연속 인덱스에 추가되면 개별 onInserted (index, 1) 호출을 하나의 onInserted (index, N)로 변환합니다. 이 변경은 RecyclerView가 변경 사항을 훨씬 더 쉽게 해결하는 데 도움이 될 수 있습니다.
견본
어댑터에 대한 getter를 사용할 수 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;
}
}
뷰 홀더 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>
뷰 홀더 클래스 :
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
있습니다.
SortedList
항목을 순서대로 유지하고 .NET Framework에 바인딩 할 수 있도록 목록의 변경 사항을 알릴 수 있는 구현입니다RecyclerView.Adapter
.
compare(Object, Object)
메소드를 사용 하여 항목을 정렬 하고 이진 검색을 사용 하여 항목을 검색합니다. 항목의 정렬 기준이 변경 될 수있는 경우 데이터 불일치를 방지하기 위해 항목을 편집하는 동안 적절한 메서드를 호출해야합니다.
SortedList.Callback
매개 변수 를 통해 항목 순서를 제어하고 알림을 변경할 수 있습니다 .
아래는의 사용 샘플입니다 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. 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).
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.
About SortedList
implementation, it is backed by an array of <T>
with a default min capacity of 10 items. Once the array is full the array is resized to 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.
It keeps items ordered using the compare(Object, Object) method and uses binary search to retrieve items. 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.
Regarding to performance they also added SortedList.BatchedCallback to carry out multiple operation at once instead of one at the time
A callback implementation that can batch notify events dispatched by the 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.
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. This change can help RecyclerView resolve changes much more easily.
If consecutive changes in the SortedList are not suitable for batching, BatchingCallback dispatches them as soon as such case is detected. After your edits on the SortedList is complete, you must always call dispatchLastEvent() to flush all changes to the Callback.
'programing tip' 카테고리의 다른 글
PhpStorm 폴더 내용 또는 전체 프로젝트 트리를 새로 고치는 방법 (0) | 2020.11.05 |
---|---|
Pandas Groupby 값 범위 (0) | 2020.11.05 |
기본 생성자 대신 TestFixtureSetUp 특성을 언제 사용합니까? (0) | 2020.11.05 |
Common Lisp에서 eq, eql, equal 및 equalp의 차이점은 무엇입니까? (0) | 2020.11.05 |
Spotify 데스크톱 애플리케이션을 개발하는 데 어떤 언어 또는 기술이 사용 되었습니까? (0) | 2020.11.05 |