Problem
I have a list of items that are displayed in android through a FirebaseRecyclerAdapter. I create this adapter with a database reference on all the list of items (let's say "posts"). The post displays also the category and if the user click on the category, I would like to update the list to display only items on that category.
Solution I tried that doesn't work I put a click listener on the "category" textview and when the user click on it I tried to instantiate a new adapter with the new database query but it doesn't work.
Other ideas: Do it outside the adpater: create a new Intent to relaunch the fragment and create a new adapter with the new query
Question Did someone deal with the same situation where on a user click you want to filter the original list of items retrieved by the adpater? What is the best solution?
Details
protected void populateViewHolder(final PostViewHolder viewHolder, final Post post, final int position) {
/* Set the post text, author and category */
viewHolder.postText.setText(post.getText());
viewHolder.postAuthor.setText(post.getAuthor());
viewHolder.postCategory.setText(post.getCategory());
/* Set a listener on category so that
I refresh data with only that category */
viewHolder.quoteCategory.setOnClickListener(new View.OnClickListener() {
Post selectedPost = getItem(position);
@Override
public void onClick(View v) {
String category = selectedPost.getCategory();
// !!!! NOW I HAVE TO CHANGE DATA SET !!! ///
I think now I can create a new Fragment with a new adapter with correct Db reference... but is this the best way? Is there a way to use the same Adapater inside the populate view passing another query?
You can use updateOptions(options) after building options with the new query.
updateOptions(newOptions)
A sample
fun changeQuery() {
val newQuery = mBaseQuery
.orderByChild("timestamp")
.limitToLast(100)
// Make new options
val newOptions = FirebaseRecyclerOptions.Builder<Post>()
.setQuery(newQuery, Post::class.java)
.build()
// Change options of adapter.
mAdapter.updateOptions(newOptions)
}
Reference
Try calling .notifyDatasetChanged()
on your adapter when the click occurs. After you have changed the dataset with the fresh firebase data.
You do not change the query, you create a new adapter and query, replace the adapter in the recycler view, and clean up the old one.
Here is an example, "changing the query" based on a selection in a spinner:
locationSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(final AdapterView<?> adapterView, final View view,
final int i, final long l) {
if (locationSpinner.getSelectedItem() != null) {
final Location location = locationSpinner.getSelectedItem();
final String indexString = String.format("open/%s/", location.getId());
final Query query = FirebaseDatabase.getInstance()
.getReference("availabilities")
.orderByChild("statusLocationDateKey")
.startAt(indexString + "0") // simplified for example
.endAt(indexString + "9"); // simplified for example
adapter = new ListingAdapter(query);
final FirebaseRecyclerAdapter oldAdapter =
(FirebaseRecyclerAdapter) listing.getAdapter();
listing.setAdapter(adapter);
if (oldAdapter != null) {
oldAdapter.cleanup();
}
}
}
Note: ListingAdapter
is a subclass of FirebaseRecyclerAdapter
and listing
is a RecyclerView
.
Also be sure to include a null check in the on destroy for the activity or fragment, since with the code above, there is no guarantee that the adapter was ever initialized, for example:
@Override
public void onDestroyView() {
if (adapter != null) {
adapter.cleanup();
}
super.onDestroyView();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With