programing tip

SortedList는 무엇입니까

itbloger 2020. 11. 5. 07:46
반응형

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();
    }
  1. 마지막으로 추가 된 항목 유지

내 리사이클 러 목록이 채워지면 즉시로드 할 캐시 된 항목이 10 개 있다고 가정 해 보겠습니다. 동시에 캐시 한 이후 변경되었을 수 있으므로 동일한 10 개 항목에 대해 네트워크에 쿼리합니다. 동일한 addAll메서드를 호출 할 수 SortedList있으며 캐시 된 항목을 내부적으로 fetchedItems로 대체합니다 (항상 마지막으로 추가 된 항목을 유지함).

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

일반에서는 List모든 항목 (목록 크기 20)이 중복됩니다. 함께 SortedList자사을 대체 항목이 콜백의를 사용하여 동일합니다 areItemsTheSame.

  1. 뷰 업데이트시기에 대한 스마트

fetchedItems가 추가되면 의 제목 onChange중 하나 이상이 Page변경된 경우에만 호출됩니다 . 당신은 무엇을 사용자 정의 할 수 있습니다 SortedList콜백의에서 찾습니다 areContentsTheSame.

  1. 성능

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

SortedListv7 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.

참고URL : https://stackoverflow.com/questions/29795299/what-is-the-sortedlistt-working-with-recyclerview-adapter

반응형