Filter in FirebaseRecyclerViewAdapter

On that question ( how to implement a SetOnItemClickListener FirebaseRecyclerViewAdapter ) I learned how to use the FirebaseRecyclerViewAdapter to get the click of recycler view, perfect.

Now I need to filter RecyclerView items made with the FirebaseRecyclerViewAdapter. In my business rule listo of the items and the user can filter them.

If it was manual, a list adding the adapter I know, but as the FirebaseRecyclerViewAdapter is responsible to prepare / update the list, someone has a suggestion how to put a filter?

Client-side filtering is not supported in the current version of FirebaseUI. It's on the roadmap, but not planned yet: https://github.com/firebase/FirebaseUI-Android/issues/15.

In the meantime, you can either use Firebase's built-in Query capabilities to limit the data. This has the advantage that only data matching the conditions will be downloaded from the server.

A great example of how advanced you can make this, is the "friend search" feature in the ShoppingList++ app of the Udacity course Firebase Essentials for Android. You can find the crucial class here in Github, but I highly recommend taking the entire course to see how this works.

the formula you listed is an intermediate result if you wanted to do an inverse radon transform without filtering in the fourier domain. an alternative is to do the entire filtered back projection algorithm using convolution in the spatial domain, which might have been faster 40 years ago; you would eventually rederive the formula you posted. however, i wouldn't recommended it now, especially not for your first reconstruction; you should really understand the hilbert transform first.

anyway, here's some matlab code which does the obligatory shepp-logan phantom filtered back projection reconstruction. i show how you can do your own filtering with the ram-lak filter. if i was really motivated, i would replace radon/iradon with some interp2 commands and summations.

phantomdata=phantom();

n=size(phantomdata,1);

theta = 0:179;
n_theta = length(theta);
[r,xp] = radon(phantomdata,theta);

% make a ram-lak filter. it's just abs(f).
n1 = length(xp);
freqs=linspace(-1, 1, n1).';
myfilter = abs( freqs );
myfilter = repmat(myfilter, [1 n_theta]);

% do my own ft domain filtering
ft_r = fftshift(fft(r,[],1),1);
filteredproj = ft_r .* myfilter;
filteredproj = ifftshift(filteredproj,1);
ift_r = real(ifft(filteredproj,[],1));

% tell matlab to do inverse fbp without a filter
i1 = iradon(ift_r, theta, 'linear', 'none', 1.0, n);

subplot(1,3,1);imagesc( real(i1) ); title('manual filtering')
colormap(gray(256)); axis image; axis off

% for comparison, ask matlab to use their ram-lak filter implementation
i2 = iradon(r, theta, 'linear', 'ram-lak', 1.0, n);

subplot(1,3,2);imagesc( real(i2) ); title('matlab filtering')
colormap(gray(256)); axis image; axis off

% for fun, redo the filtering wrong on purpose
% exclude high frequencies to create a low-resolution reconstruction
myfilter( myfilter > 0.1 ) = 0;
ift_r = real(ifft(ifftshift(ft_r .* myfilter,1),[],1));
i3 = iradon(ift_r, theta, 'linear', 'none', 1.0, n);

subplot(1,3,3);imagesc( real(i3) ); title('low resolution filtering')
colormap(gray(256)); axis image; axis off

here is what i would try. first check out the accepted answer to the question linked below. it provides some very good insight into how firebase queries work. i'd consider the info trusted since the answer is by someone on the firebase team:

how to separate initial data load from incremental children with firebase?

so, based on the answer to the question linked above and the fact that the firebaserecycleradapter is backed by a firebasearray which is populated using a childeventlistener i would add a single value event listener on the same database reference used to populate your firebaserecycleradapter. something like this:

//create database reference that will be used for both the
//firebaserecycleradapter and the single value event listener
dbref = firebasedatabase.getinstance().getreference();

//setup firebaserecycleradapter
madapter = new firebaserecycleradapter<model, yourviewholder>(
                model.class, r.layout.your_layout, yourviewholder.class, dbref) {

                @override
                public void populateviewholder(yourviewholder holder, model model, int position){

                     //your code for populating each recycler view item

                };

mrecyclerview.setadapter(madapter);

//add the listener for the single value event that will function
//like a completion listener for initial data load of the firebaserecycleradapter
dbref.addlistenerforsinglevalueevent(new valueeventlistener() {
             @override
             public void ondatachange(datasnapshot datasnapshot) {
                 //ondatachange called so remove progress bar

                 //make a call to datasnapshot.haschildren() and based 
                 //on returned value show/hide empty view 

                 //use helper method to add an observer to recyclerview    
             }

             @override
             public void oncancelled(databaseerror databaseerror) {

             }
      });

that would handle the initial setup of the recyclerview. when ondatachange is called on the single value event listener use a helper method to add an observer to the firebaserecycleradapter to handle any subsequent additions/deletions to database location.

mobserver = new recyclerview.adapterdataobserver() {
            @override
            public void onitemrangeinserted(int positionstart, int itemcount) {
                //perform check and show/hide empty view
            }

            @override
            public void onitemrangeremoved(int positionstart, int itemcount) {
                //perform check and show/hide empty view
            }
           };
madapter.registeradapterdataobserver(mobserver);

well, i think i figured out a way.

just placed some conditions in the code.

here's the updated code:

    if (datasnapshot.getvalue() != null) {

         if (datasnapshot.haschild("pname") && datasnapshot.haschild("purl") && datasnapshot.haschild("clat") && datasnapshot.haschild("clng")) {

                 map<string, string> map = (map<string, string>) datasnapshot.getvalue();
                 pa = map.get("pname");
                 ua = map.get("purl");
                 string clats = map.get("clat").trim();
                 currentltau = double.parsedouble(clats);
                 string clngs = map.get("clng").trim();
                 currentlnau = double.parsedouble(clngs);

                 viewholder.setpname(pa);
                 viewholder.setpurl(ua);
                 viewholder.setcurrentlatau(string.valueof(currentltau));
                 viewholder.setcurrentlngau(string.valueof(currentlnau));

          }
     }

and now everything works perfectly fine!

in your case, you should use class instead of ng-class because you render the class name directly on the html without evaluation.

<div ng-controller="myctrl">
   <i class="{{phone.trueval  | checkmark }}">{{phone.trueval  | checkmark}}</i>
   <i class="{{phone.falseval | checkmark }}">{{phone.falseval | checkmark}}</i>
</div>

demo


Tags: Android Firebase Android Recyclerview Firebase Realtime Database Firebaseui