Chapter 4. Filtering Observables

In the previous chapter, we learned how to set up a new Android project with RxJava and how to create an Observable list to populate RecyclerView. We now know how to create an Observable from scratch, a list, or an existing classic Java function.

In this chapter, we will dive into the essence of an Observable sequence: filtering. We will learn how to select only the values we want from an emitting Observable, how to obtain a finite number of values, and how to handle overflow scenarios, and a few more useful tricks.

Filtering a sequence

RxJava lets us use filter() to keep certain values that we don't want out of the sequence we are observing. In the previous chapter, we used the installed apps list in a few examples, but what if we want to show only the installed app whose name starts with C? In this new example, we will use the same list, but we will filter it, passing the proper predicate to the filter() function to include the values we want.

The loadList() function we had in the previous chapter changes like this:

private void loadList(List<AppInfo> apps) {
    mRecyclerView.setVisibility(View.VISIBLE);

    Observable.from(apps)
            .filter((appInfo) ->  appInfo.getName().startsWith("C"))
            .subscribe(new Observer<AppInfo>() {
                @Override
                public void onCompleted() {
                    mSwipeRefreshLayout.setRefreshing(false);
                }

                @Override
                public void onError(Throwable e) {
                    Toast.makeText(getActivity(), "Something went  south!", Toast.LENGTH_SHORT).show();
                    mSwipeRefreshLayout.setRefreshing(false);
                }

                @Override
                public void onNext(AppInfo appInfo) {
                    mAddedApps.add(appInfo);
                    mAdapter.addApplication(mAddedApps.size() - 1,  appInfo);
                }
            });
}

We have added the following line to the loadList() function from the previous chapter:

.filter((appInfo) -> appInfo.getName().startsWith("C"))

After the creation of an Observable, we are filtering out every emitted element that has a name starting with a letter that is not C. Let's have this in Java 7 syntax in order to clarify the types here:

.filter(new Func1<AppInfo, Boolean>() {
    @Override
    public Boolean call(AppInfo appInfo) {
        return appInfo.getName().startsWith("C");
    }
})

We are passing a new Func1 object to filter(), that is, a function that has just one parameter. Func1 has an AppInfo object as its parameter type and it returns a Boolean object. The filter() function will return true only if the condition is verified. At this point, the value will be emitted and received by all the Observers.

As you can imagine, filter() is critically useful to create the perfect sequence that we need from the Observable sequence we get. We don't need to know the source of the Observable sequence or why it's emitting tons of different elements. We just want a useful subset of these elements to create a new sequence we can use in our app. This mindset enforces the separation and abstraction skills of our coding life.

One of the most common uses of filter() is filtering null objects:

.filter(new Func1<AppInfo, Boolean>() {
    @Override
    public Boolean call(AppInfo appInfo) {
        return appInfo != null;
    }
})

This seems to be simple, and there is a lot of boilerplate code for something this simple, but this will save us from checking for null values in the onNext() call, letting us focus on the actual app logic.

The next figure shows the installed apps list, filtered by names starting with C:

Filtering a sequence
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.134.17