Once and only once

An emitting Observable sequence could emit duplicates by error or by design. The distinct() and distinctUntilChanged() functions allow us to deal smoothly with duplicates.

Distinct

What if we want to be absolutely sure that we process a specific value only once? We can get rid of the duplicates by applying the distinct() function to our Observable sequence. Like takeLast(), distinct() works with a completed sequence and to achieve this duplication filtering, it needs to keep a track of every emitted item. This is a memory usage concern that you have to keep in mind if you are dealing with a huge sequence or big emitted items.

The next figure shows how we can create a sequence with no duplicate working on an Observable source that emits numbers and emits 1 and 2 twice:

Distinct

To create our example sequence, we are going to use a few methods we have learned so far:

  • take(): This is to have a small set of recognizable items
  • repeat(): This is to create a larger sequence containing a few duplicates

Then, we will apply the distinct() function to get rid of the duplicates.

Note

We are programmatically creating a sequence full of duplicates and then filtering them out. It sounds crazy, but it's for the sake of the example and is a useful exercise to use what we have learned so far.

Observable<AppInfo> fullOfDuplicates = Observable.from(apps)
        .take(3)
        .repeat(3);

The fullOfDuplicates variable contains the first three elements of our installed apps list repeated three times: nine elements and a lot of duplicates. Then, we apply distinct():

fullOfDuplicates.distinct()
        .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);
            }
        });

As a result, obviously, we get:

Distinct

DistinctUntilChanged

What if we want to get notified when an Observable sequence emits a new value that is different from the previous one? Let's suppose we are observing a temperature sensor, emitting the room temperature every second:

21°… 21°… 21°… 21°… 22°

Every time we get a new value, we update a display showing the current temperature. We want to play resource conservative and we don't want to update the display if the value is still the same. We want to ignore all repeated values and just get notified when the temperature actually changes. The distinctUntilChanged()filtering function will do the trick. It simply ignores all the duplicates and emits only the new value.

The next figure shows, in a graphical way, how we can apply distinctUntilChanged() to an existing sequence to create a new sequence that won't emit elements that have already been emitted:

DistinctUntilChanged
..................Content has been hidden....................

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