Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FirebaseRecyclerAdapter - how to change database query after creation

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?

like image 578
DavideN Avatar asked Aug 03 '16 16:08

DavideN


Video Answer


3 Answers

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

like image 101
Arush Kharbanda Avatar answered Oct 08 '22 20:10

Arush Kharbanda


Try calling .notifyDatasetChanged() on your adapter when the click occurs. After you have changed the dataset with the fresh firebase data.

like image 42
Josef Korbel Avatar answered Oct 08 '22 19:10

Josef Korbel


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();
}
like image 1
Tony BenBrahim Avatar answered Oct 08 '22 19:10

Tony BenBrahim