I've created RecyclerView which contains simple list of words (String names of GroupVc objects). As list can be very long I want to make it filterable with SearchView in Toolbar. Architecture of my application is based on Android Architecture Components, where all GroupVc objects exist in Room database and access to DataBase from UI is provided through ViewModel and Repository objects. I'm filing my RecyclerView with list of all GroupsVc wrapped in LiveData to keep it updated. My problem is that I don't know how to make RecyclerView filterable. I tried to do it with implementing of Filterable Interface in adapter:
public class GroupsVcAdapter extends
RecyclerView.Adapter<GroupsViewHolder> implements Filterable{
private LayoutInflater mInflater;
private List<GroupVc> mGroupsVc;
private List<GroupVc> filteredGroupsVc;
private OnItemClicked onClick;
public GroupsVcAdapter(Context context, OnItemClicked onClick) {
mInflater = LayoutInflater.from(context);
this.onClick = onClick;
}
public List<GroupVc> getmGroupsVc() {
return mGroupsVc;
}
@Override
public GroupsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = mInflater.inflate(R.layout.layout_list_of_groups, parent, false);
return new GroupsViewHolder(itemView, onClick);
}
@Override
public void onBindViewHolder(final GroupsViewHolder holder, int position) {
if (mGroupsVc != null) {
GroupVc current = mGroupsVc.get(position);
holder.getNameView().setText(current.getNameGroup());
} else {
holder.getNameView().setText(R.string.nogroups);
}
}
public void setGroupsVc(List<GroupVc> mGroupsVc) {
this.mGroupsVc = mGroupsVc;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
if (mGroupsVc != null)
return mGroupsVc.size();
else return 0;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mGroupsVc = (List<GroupVc>) results.values;
notifyDataSetChanged();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
filteredGroupsVc = null;
if (constraint.length() == 0) {
filteredGroupsVc = mGroupsVc;
} else {
filteredGroupsVc = getFilteredResults(constraint.toString().toLowerCase());
}
FilterResults results = new FilterResults();
results.values = filteredGroupsVc;
return results;
}
};
}
protected List<GroupVc> getFilteredResults(String constraint) {
List<GroupVc> results = new ArrayList<>();
for (GroupVc item : mGroupsVc) {
if (item.getNameGroup().toLowerCase().contains(constraint)) {
results.add(item);
}
}
return results;
}
}
And then in Activity I've written a method:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_activity_words, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String text) {
return false;
}
@Override
public boolean onQueryTextChange(String text) {
adapter.getFilter().filter(text);
return true;
}
});
return true;
}
The result was that my RecyclerView got filtered correctly but it wasn't restored after I closed SearchView. The only way to do it is to reload activity. **So I'm interested in How can I restore RecyclerView's list and can I use for filtering any LiveData's capacities?** Below I post the complete code of Activity, ViewModel and Repository:
Activity
public class GroupsActivity extends AppCompatActivity {
private static final String DELETE_DIALOG = "Delete dialog";
private static final String EDIT_DIALOG = "Edit dialog";
private RecyclerView mRecyclerView;
private GroupsVcAdapter adapter;
private GroupsViewModel mGroupsViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_groups);
//Creating of toolbar with title Groups
Toolbar myToolbar = findViewById(R.id.toolbar_groups);
setSupportActionBar(myToolbar);
//Enable Up Button
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
//RecyclerView containing the list of groups with sound icons
mRecyclerView = initRecyclerView();
//Using ViewModel to observe GroupVc data
mGroupsViewModel = ViewModelProviders.of(this).get(GroupsViewModel.class);
mGroupsViewModel.getAllGroups().observe(this, new Observer<List<GroupVc>>() {
@Override
public void onChanged(@Nullable List<GroupVc> groupVcs) {
adapter.setGroupsVc(groupVcs);
}
});
}
private RecyclerView initRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.groups_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
OnItemClicked listener = (v, position) -> {
switch (v.getId()) {
case R.id.delete_group:
Log.i(DELETE_DIALOG, "Delete button");
break;
case R.id.edit_group:
Log.i(EDIT_DIALOG, "Edit button");
break;
case R.id.surface:
Log.i(SURFACE, "Surface button");
break;
}
};
adapter = new GroupsVcAdapter(this, listener);
recyclerView.setAdapter(adapter);
return recyclerView;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_activity_words, menu);
// Associate searchable configuration with the SearchView
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =
(SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String text) {
return false;
}
@Override
public boolean onQueryTextChange(String text) {
adapter.getFilter().filter(text);
return true;
}
});
return true;
}
}
ViewModel
public class GroupsViewModel extends AndroidViewModel {
private LiveData<List<GroupVc>> mAllGroups;
private GroupRepository mRepository;
public GroupsViewModel(@NonNull Application application) {
super(application);
mRepository = new GroupRepository(application);
mAllGroups = mRepository.getAllGroupVc();
}
public LiveData<List<GroupVc>> getAllGroups() {
return mAllGroups;
}
}
Repository
public class GroupRepository {
private LiveData<List<GroupVc>> mAllGroups;
private GroupVcDao mGroupVcDao;
public GroupRepository(Application application) {
AppDatabase db = AppDatabase.getInstance(application);
mGroupVcDao = db.groupVcDao();
mAllGroups = mGroupVcDao.getAllGroupVc();
}
public LiveData<List<GroupVc>> getAllGroupVc() {
return mAllGroups;
}
}