소개
정확히 당신이 어떤 문제를 겪고 있는지 당신의 질문에서 명확하지 않기 때문에, 나는이 기능을 구현하는 방법에 대한이 빠른 연습을 작성했습니다. 여전히 궁금한 점이 있으면 언제든지 문의하십시오.
이 GitHub 리포지토리 에서 내가 말하는 모든 것에 대한 실제 사례가 있습니다 .
예제 프로젝트에 대한 자세한 내용을 보려면 프로젝트 홈페이지를 방문하십시오 .
어쨌든 결과는 다음과 같습니다.
데모 앱으로 먼저 플레이하고 싶다면 Play 스토어에서 설치할 수 있습니다.
어쨌든 시작할 수 있습니다.
설정 SearchView
폴더에 res/menu
이라는 새 파일을 만듭니다 main_menu.xml
. 그것에서 항목을 추가하고 설정 actionViewClass
에 android.support.v7.widget.SearchView
. 지원 라이브러리를 사용하고 있으므로 지원 라이브러리의 네임 스페이스를 사용하여 actionViewClass
속성 을 설정해야 합니다. xml 파일은 다음과 같아야합니다.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_search"
android:title="@string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
당신에 Fragment
또는 Activity
평소처럼이 메뉴 XML을 팽창해야합니다, 당신은 찾아보실 수 있습니다 MenuItem
포함되는 SearchView
및 구현 OnQueryTextListener
우리가에 입력 한 텍스트에 대한 변경 사항을 수신하는 데 사용하려고한다 SearchView
:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public boolean onQueryTextChange(String query) {
// Here is where we are going to implement the filter logic
return false;
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
이제 SearchView
사용할 준비가되었습니다. 우리는 구현을 onQueryTextChange()
마치면 나중에 필터 로직을 구현할 것 Adapter
입니다.
설정 Adapter
가장 먼저 이것은이 예제에 사용할 모델 클래스입니다.
public class ExampleModel {
private final long mId;
private final String mText;
public ExampleModel(long id, String text) {
mId = id;
mText = text;
}
public long getId() {
return mId;
}
public String getText() {
return mText;
}
}
에 텍스트를 표시하는 것은 기본 모델 일뿐 RecyclerView
입니다. 이것은 텍스트를 표시하는 데 사용할 레이아웃입니다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="model"
type="com.github.wrdlbrnft.searchablerecyclerviewdemo.ui.models.ExampleModel"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@{model.text}"/>
</FrameLayout>
</layout>
보시다시피 데이터 바인딩을 사용합니다. 데이터 바인딩 작업을 해 본 적이 없다면 실망하지 마십시오! 매우 간단하고 강력하지만이 답변의 범위에서 어떻게 작동하는지 설명 할 수 없습니다.
이것은 수업을 ViewHolder
위한 것 ExampleModel
입니다 :
public class ExampleViewHolder extends RecyclerView.ViewHolder {
private final ItemExampleBinding mBinding;
public ExampleViewHolder(ItemExampleBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
public void bind(ExampleModel item) {
mBinding.setModel(item);
}
}
또 특별한 것은 없습니다. 위의 레이아웃 xml에서 정의한대로 데이터 바인딩을 사용하여 모델 클래스를이 레이아웃에 바인딩합니다.
이제 우리는 마침내 어댑터 작성이라는 정말 흥미로운 부분에 도달 할 수 있습니다. 나는 기본 구현을 건너 뛰고 Adapter
대신이 답변과 관련된 부분에 집중할 것입니다.
그러나 먼저 우리가 이야기해야 할 것이 있습니다 : SortedList
클래스.
정렬 된 목록
은 SortedList
의 일부인 완전히 놀라운 도구입니다 RecyclerView
도서관. Adapter
데이터 세트의 변경 사항에 대해 알리고 매우 효율적인 방식으로 처리합니다. 당신이해야 할 유일한 것은 요소의 순서를 지정하는 것입니다. compare()
두 개의 요소를 SortedList
a처럼 비교 하는 메소드를 구현하여이를 수행해야 합니다 Comparator
. 그러나를 정렬하는 대신 ! List
에서 항목을 정렬하는 데 사용됩니다 RecyclerView
.
SortedList
와 상호 작용 Adapter
하는 관통 Callback
당신이 구현해야 클래스 :
private final SortedList.Callback<ExampleModel> mCallback = new SortedList.Callback<ExampleModel>() {
@Override
public void onInserted(int position, int count) {
mAdapter.notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
mAdapter.notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
mAdapter.notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
mAdapter.notifyItemRangeChanged(position, count);
}
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
}
같은 콜백 상단의 방법에서 onMoved
, onInserted
등 당신은 동등한 당신의 방법을 알려 호출해야 Adapter
. 하단의 세 가지 방법 compare
, areContentsTheSame
및areItemsTheSame
당신은 이러한 개체가 화면에 나타납니다 주문 어떤 종류의 객체 표시 할 것에과에 따라 구현해야합니다.
이 방법들을 하나씩 살펴 보자.
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
이것이 compare()
내가 이전에 이야기했던 방법입니다. 이 예에서는 Comparator
두 모델을 비교하는 호출을 전달합니다 . 화면에 항목을 알파벳 순서로 표시하려면. 이 비교기는 다음과 같습니다.
private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return a.getText().compareTo(b.getText());
}
};
이제 다음 방법을 살펴 보겠습니다.
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
이 방법의 목적은 모델의 내용이 변경되었는지 확인하는 것입니다. 이를 SortedList
사용하여 변경 이벤트를 호출 RecyclerView
해야하는지 여부, 즉 이전 버전과 새 버전을 교차 페이드해야하는지 여부를 결정 합니다. 클래스가 정확 equals()
하고 hashCode()
구현 된 모델 을 만들 경우 일반적으로 위와 같이 구현할 수 있습니다. 클래스에 equals()
and hashCode()
구현을 추가하면 ExampleModel
다음과 같이 보일 것입니다.
public class ExampleModel implements SortedListAdapter.ViewModel {
private final long mId;
private final String mText;
public ExampleModel(long id, String text) {
mId = id;
mText = text;
}
public long getId() {
return mId;
}
public String getText() {
return mText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExampleModel model = (ExampleModel) o;
if (mId != model.mId) return false;
return mText != null ? mText.equals(model.mText) : model.mText == null;
}
@Override
public int hashCode() {
int result = (int) (mId ^ (mId >>> 32));
result = 31 * result + (mText != null ? mText.hashCode() : 0);
return result;
}
}
빠른 참고 : Android Studio, IntelliJ 및 Eclipse와 같은 대부분의 IDE 에는 버튼을 한 번만 누르면 생성 equals()
및 hashCode()
구현할 수 있는 기능이 있습니다! 따라서 직접 구현할 필요는 없습니다. 인터넷에서 IDE에서 어떻게 작동하는지 찾아보십시오!
이제 마지막 방법을 살펴 보자.
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
는 SortedList
두 항목이 같은 일을 참조하는지 확인하기 위해이 방법을 사용합니다. 가장 간단한 용어로 ( SortedList
작동 방식을 설명하지 않고 ) 객체가 이미 포함되어 List
있는지, 애니메이션을 추가, 이동 또는 변경 해야하는지 결정하는 데 사용 됩니다. 모델에 ID가있는 경우 일반적으로이 방법에서 ID 만 비교합니다. 그들이 그것을 확인하는 다른 방법을 알아낼 필요가 없다면, 그러나 당신은 이것을 구현하는 것은 당신의 특정 앱에 달려 있습니다. 일반적으로 모든 모델에 ID를 제공하는 가장 간단한 옵션입니다. 예를 들어 데이터베이스에서 데이터를 쿼리하는 경우 기본 키 필드가 될 수 있습니다.
SortedList.Callback
올바르게 구현 하면 다음과 같은 인스턴스를 만들 수 있습니다 SortedList
.
final SortedList<ExampleModel> list = new SortedList<>(ExampleModel.class, mCallback);
생성자의 첫 번째 매개 변수로 SortedList
모델의 클래스를 전달해야합니다. 다른 매개 변수는 SortedList.Callback
위에서 정의한 것입니다.
우리가 구현하는 경우 : 이제 본론하자 Adapter
A의를 SortedList
다음과 비슷한 모습이 될 것입니다 그것은 :
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@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(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
});
private final LayoutInflater mInflater;
private final Comparator<ExampleModel> mComparator;
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
mInflater = LayoutInflater.from(context);
mComparator = comparator;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mSortedList.get(position);
holder.bind(model);
}
@Override
public int getItemCount() {
return mSortedList.size();
}
}
Comparator
우리가 같은 사용할 수 있도록 항목이 생성자를 통해 전달되는 정렬하는 데 사용 Adapter
항목이 다른 순서로 표시하기로하는 경우도 있습니다.
이제 거의 다 끝났습니다! 그러나 먼저에 항목을 추가하거나 제거 할 수있는 방법이 필요합니다 Adapter
. 이를 위해 다음에 Adapter
항목을 추가하고 제거 할 수있는 메소드를 추가 할 수 있습니다 SortedList
.
public void add(ExampleModel model) {
mSortedList.add(model);
}
public void remove(ExampleModel model) {
mSortedList.remove(model);
}
public void add(List<ExampleModel> models) {
mSortedList.addAll(models);
}
public void remove(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (ExampleModel model : models) {
mSortedList.remove(model);
}
mSortedList.endBatchedUpdates();
}
우리는 SortedList
이미 통지 메소드를 호출 할 필요가 없습니다 SortedList.Callback
! 그 외에도, 이러한 메소드의 구현 List
은 모델 을 제거하는 remove 메소드를 제외하고는 매우 간단합니다 . 은 이후 SortedList
우리가리스트를 반복 할 필요가 하나의 객체를 제거하고 하나를 사용하여 모델 하나를 제거 할 수 있습니다 하나의 제거 방법이있다. beginBatchedUpdates()
처음에 전화 하면 모든 변경 사항을 일괄 처리하고 SortedList
성능을 향상시킵니다. 우리가 전화 endBatchedUpdates()
하면 RecyclerView
모든 변경 사항에 대해 한 번에 알립니다.
또한 이해해야 할 것은 객체를 객체에 추가하고 SortedList
이미 객체를 추가하면 SortedList
다시 추가되지 않는다는 것입니다. 대신 메소드를 SortedList
사용하여 areContentsTheSame()
객체가 변경되었는지 확인하고 항목이있는 RecyclerView
경우 업데이트됩니다.
어쨌든, 내가 일반적으로 선호하는 것은 한 RecyclerView
번 에 모든 항목을 교체 할 수있는 한 가지 방법입니다 . 에없는 모든 것을 제거 List
하고에서 누락 된 모든 항목을 추가하십시오 SortedList
.
public void replaceAll(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (int i = mSortedList.size() - 1; i >= 0; i--) {
final ExampleModel model = mSortedList.get(i);
if (!models.contains(model)) {
mSortedList.remove(model);
}
}
mSortedList.addAll(models);
mSortedList.endBatchedUpdates();
}
이 방법은 다시 모든 업데이트를 일괄 처리하여 성능을 향상시킵니다. 첫 번째 루프는 시작시 항목을 제거하면 해당 항목 이후에 나오는 모든 항목의 색인이 엉망이되어 데이터 불일치와 같은 문제가 발생할 수 있으므로 반대입니다. 그 후에 우리 List
는 SortedList
using addAll()
에 추가 하여 이미 존재하지 않는 모든 항목을 추가합니다. SortedList
위에서 설명한 것처럼 이미 존재 SortedList
하지만 변경된 모든 항목을 업데이트합니다 .
그리고 이것으로 Adapter
완성되었습니다. 모든 것이 다음과 같이 보일 것입니다 :
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@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(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1 == item2;
}
});
private final Comparator<ExampleModel> mComparator;
private final LayoutInflater mInflater;
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
mInflater = LayoutInflater.from(context);
mComparator = comparator;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(mInflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mSortedList.get(position);
holder.bind(model);
}
public void add(ExampleModel model) {
mSortedList.add(model);
}
public void remove(ExampleModel model) {
mSortedList.remove(model);
}
public void add(List<ExampleModel> models) {
mSortedList.addAll(models);
}
public void remove(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (ExampleModel model : models) {
mSortedList.remove(model);
}
mSortedList.endBatchedUpdates();
}
public void replaceAll(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (int i = mSortedList.size() - 1; i >= 0; i--) {
final ExampleModel model = mSortedList.get(i);
if (!models.contains(model)) {
mSortedList.remove(model);
}
}
mSortedList.addAll(models);
mSortedList.endBatchedUpdates();
}
@Override
public int getItemCount() {
return mSortedList.size();
}
}
이제 누락 된 것은 필터링을 구현하는 것입니다!
필터 로직 구현
필터 로직을 구현하려면 먼저 List
가능한 모든 모델 을 정의 해야합니다. 예를 들어 내가 작성 List
의 ExampleModel
영화의 배열에서 인스턴스를 :
private static final String[] MOVIES = new String[]{
...
};
private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return a.getText().compareTo(b.getText());
}
};
private ExampleAdapter mAdapter;
private List<ExampleModel> mModels;
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mAdapter = new ExampleAdapter(this, ALPHABETICAL_COMPARATOR);
mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
mBinding.recyclerView.setAdapter(mAdapter);
mModels = new ArrayList<>();
for (String movie : MOVIES) {
mModels.add(new ExampleModel(movie));
}
mAdapter.add(mModels);
}
여기서는 특별한 일이 없습니다. 인스턴스화하고 Adapter
로 설정했습니다 RecyclerView
. 그런 List
다음 MOVIES
배열 의 영화 이름에서 모델을 만듭니다 . 그런 다음 모든 모델을에 추가합니다 SortedList
.
이제 onQueryTextChange()
이전에 정의한 내용 으로 돌아가서 필터 로직 구현을 시작할 수 있습니다.
@Override
public boolean onQueryTextChange(String query) {
final List<ExampleModel> filteredModelList = filter(mModels, query);
mAdapter.replaceAll(filteredModelList);
mBinding.recyclerView.scrollToPosition(0);
return true;
}
이것은 다시 매우 직설적입니다. 우리는 메소드를 호출 filter()
하고, 전달 List
의 ExampleModel
잘 쿼리 문자열 등으로의. 그런 다음를 호출하고 replaceAll()
에 의해 반환 된 Adapter
필터링 된 항목을 전달 List
합니다 filter()
. 우리는 또한 전화가 scrollToPosition(0)
온 RecyclerView
무언가를 검색 할 때 사용자가 항상 모든 항목을 볼 수 있도록 할 수 있습니다. 그렇지 않으면, RecyclerView
필터링하는 동안 아래로 스크롤 된 위치에 남아서 몇 개의 항목을 숨길 수 있습니다. 맨 위로 스크롤하면 검색하는 동안 사용자 경험이 향상됩니다.
이제 남은 것은 filter()
스스로 구현하는 것입니다.
private static List<ExampleModel> filter(List<ExampleModel> models, String query) {
final String lowerCaseQuery = query.toLowerCase();
final List<ExampleModel> filteredModelList = new ArrayList<>();
for (ExampleModel model : models) {
final String text = model.getText().toLowerCase();
if (text.contains(lowerCaseQuery)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
여기서 가장 먼저하는 일은 toLowerCase()
쿼리 문자열을 호출 하는 것입니다. 검색 기능이 대소 문자를 구분하는 것을 원하지 않으며 toLowerCase()
비교할 모든 문자열 을 호출 하여 대소 문자와 상관없이 동일한 결과를 반환 할 수 있습니다. 그런 다음 List
전달 된 모든 모델을 반복 하고 쿼리 문자열이 모델의 텍스트에 포함되어 있는지 확인합니다. 이 경우 모델이 필터링 된 항목에 추가됩니다 List
.
그리고 그게 다야! 위의 코드는 API 레벨 7 이상에서 실행되며 API 레벨 11부터 무료로 항목 애니메이션을 얻을 수 있습니다!
나는 이것이 전체 내용을 실제보다 더 복잡하게 만드는 매우 상세한 설명이라는 것을 알고 있지만, 우리는이 모든 문제를 일반화 Adapter
하고 SortedList
훨씬 더 기반을 기반으로 구현할 수있는 방법이 있습니다 .
문제점 일반화 및 어댑터 단순화
이 섹션에서는 스택 오버플로에 대한 답변에 대한 문자 제한에 대해 실행 중이지만 대부분 위에서 이미 설명 했으므로 변경 사항을 요약하기 위해 자세히 설명하지는 않습니다. 기본 Adapter
클래스를 구현할 수 있습니다. 인스턴스 SortedList
를 바인딩하고 모델을 처리하고 이미 ViewHolder
에 Adapter
기반 을 구현하는 편리한 방법을 제공 합니다 SortedList
. 이를 위해 우리는 두 가지 일을해야합니다.
ViewModel
모든 모델 클래스가 구현해야하는 인터페이스 를 만들어야합니다
- 모델을 자동으로 바인딩하는 데 사용할 수
ViewHolder
있는 bind()
메서드 를 정의 하는 하위 클래스 를 만들어야합니다 Adapter
.
이를 통해 RecyclerView
모델을 구현하고 해당 ViewHolder
구현 을 통해 표시 할 내용에 집중할 수 있습니다 . 이 기본 클래스를 사용하면 Adapter
및 의 복잡한 세부 사항에 대해 걱정할 필요가 없습니다 SortedList
.
정렬 된 목록 어댑터
이 때문에 기본 클래스를 구현하거나 여기에 전체 소스 코드를 추가 할 수 있지만이 기본 클래스의 전체 소스 코드를 찾을 수의 각 단계를 통해 갈 수 StackOverflow의 I에 대한 답변 문자 제한의 - 나는 그것이라고 SortedListAdapter
-이에 GitHub 요지 .
당신의 인생을 간단하게하기 위해 jCenter에 라이브러리가 게시되었습니다 SortedListAdapter
! 그것을 사용하려면 앱의 build.gradle 파일 에이 종속성을 추가하기 만하면됩니다.
compile 'com.github.wrdlbrnft:sorted-list-adapter:0.2.0.1'
이 라이브러리 에 대한 자세한 정보 는 라이브러리 홈페이지에서 찾을 수 있습니다 .
SortedListAdapter 사용
사용하려면 SortedListAdapter
다음 두 가지 사항을 변경해야합니다.
ViewHolder
연장되도록 변경하십시오 SortedListAdapter.ViewHolder
. type 매개 변수는 ViewHolder
이 경우에 바인딩되어야하는 모델이어야합니다 ExampleModel
. performBind()
대신 데이터를 모델에 바인딩해야합니다 bind()
.
public class ExampleViewHolder extends SortedListAdapter.ViewHolder<ExampleModel> {
private final ItemExampleBinding mBinding;
public ExampleViewHolder(ItemExampleBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
@Override
protected void performBind(ExampleModel item) {
mBinding.setModel(item);
}
}
모든 모델이 ViewModel
인터페이스를 구현해야합니다 .
public class ExampleModel implements SortedListAdapter.ViewModel {
...
}
그 후에 우리는 더 이상 필요없는 모든 것을 ExampleAdapter
확장 SortedListAdapter
하고 제거 하기 위해 업데이트 해야합니다. type 매개 변수는 작업중인 모델의 유형이어야합니다 (이 경우) ExampleModel
. 그러나 다른 유형의 모델로 작업하는 경우 type 매개 변수를로 설정하십시오 ViewModel
.
public class ExampleAdapter extends SortedListAdapter<ExampleModel> {
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
super(context, ExampleModel.class, comparator);
}
@Override
protected ViewHolder<? extends ExampleModel> onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
protected boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
@Override
protected boolean areItemContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
}
그 후 우리는 끝났습니다! 언급하지만 마지막으로 남은 하나는 SortedListAdapter
동일하지 않습니다 add()
, remove()
또는 replaceAll()
우리의 원래 방법을 ExampleAdapter
했다합니다. 별도의 Editor
객체를 사용 하여 edit()
메소드를 통해 액세스 할 수있는 목록의 항목을 수정합니다 . 따라서 호출하거나 호출해야 할 항목 edit()
을 추가하려면이 Editor
인스턴스 에서 항목을 추가 및 제거해야합니다. 완료 한 후에는 commit()
변경 사항을 다음에 적용하십시오 SortedList
.
mAdapter.edit()
.remove(modelToRemove)
.add(listOfModelsToAdd)
.commit();
이 방법으로 수행 한 모든 변경 사항은 함께 배치되어 성능을 향상시킵니다. replaceAll()
위의 장에서 구현 한 방법은이 Editor
객체에도 있습니다.
mAdapter.edit()
.replaceAll(mModels)
.commit();
전화 commit()
를 잊어 버린 경우 변경 사항이 적용되지 않습니다!