P E R AT I O N S • Observer-pattern for data- streams with operators. • Create operators ✦ Create/Interval/Range • Transform operators ✦ Map/FlatMap/Window • Filter operators ✦ Filter/Take/Debounce • Combining operators
X A M P L E 1 - C O M P O S I N G Use Case: Create a User account via a REST API final public Observable<User> addUser(@NonNull final User user) { return pseudoEndPoint.addUser(user); }
X A M P L E 1 - C O M P O S I N G nue = new NetworkUnavailableError(context.getString(R.string.network_unavailable)); private Observable<Boolean> checkNetworkStatus() { return Observable.<Boolean>create(subscriber -> { final NetworkInfo net = cm.getActiveNetworkInfo(); if (net == null || !net.isConnected()) { subscriber.onError(nue); } subscriber.onNext(true); subscriber.onCompleted(); }).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()); } final public Observable<User> addUser(@NonNull final User user) { return checkNetworkStatus().flatMap( aBoolean -> { return pseudoEndPoint.addUser(user); } ); } Use Case: Create a User account via a REST API (must be online)
X A M P L E 1 - C O M P O S I N G final public Observable<User> addUser(@NonNull final User user) { return pseudoEndPoint.addUser(user); } nue = new NetworkUnavailableError(context.getString(R.string.network_unavailable)); private Observable<Boolean> checkNetworkStatus() { return Observable.<Boolean>create(subscriber -> { final NetworkInfo net = cm.getActiveNetworkInfo(); if (net == null || !net.isConnected()) { subscriber.onError(nue); } subscriber.onNext(true); subscriber.onCompleted(); }).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()); } final public Observable<User> addUser(@NonNull final User user) { return checkNetworkStatus().flatMap( aBoolean -> { return pseudoEndPoint.addUser(user); } ); } nue = new NetworkUnavailableError(context.getString(R.string.network_unavailable)); public Observable<AuthToken> getAccessToken(@NonNull final String apiKey, @NonNull final String secretKey) { final String credentials = String.format("%s:%s", apiKey, secretKey); final String authString = String.format("Basic %s", Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP)); return endpoint.postApiAuthorisation(authString, "client_credentials") .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()); } private Observable<Boolean> checkNetworkStatus() { … } public Observable<User> addNewUser(@NonNull final User user) { final String headerAuthorisation = String.format("Bearer %s", authToken.accessToken); return checkNetworkStatus().flatMap(aBoolean -> { return endpoint.postNewUser(headerAuthorisation, user).onErrorResumeNext(throwable -> { if (throwable instanceof UnauthorizedError) { // refresh auth token return getAccessToken(keyAPi, keySecret).flatMap(authToken1 -> { synchronized (authToken) { authToken.merge(authToken1); return addNewUser(user); } }); } else { return Observable.error(throwable); } }); }); } Use Case: Create a User account via a REST API (must be online) using OAuth authentication
X A M P L E 2 - C O M B I N I N G Use Case: Receive HR metrics private Observable<HrSession>createHrSessionListenerObservable() { return Observable.<HrSession>create(subscriber-> { final HrCallback callback=hrSession->{ subscriber.onNext(hrSession); // Check if we are done if(hrSession.getEvent()==HrEventType.HR_DONE){ subscriber.onCompleted(); } }; // Execute with our listener final Response response=WearableSDK.hrSessionListener(callback); if(response.hasError()){ subscriber.onError(new WearableError(response.getError())); }else{ Log.d(TAG,"createHrSessionListenerObservable {code=%d}",response.getCode()); } }); }
X A M P L E 2 - C O M B I N I N G Use Case: Receive HR metrics AND poll battery status private Observable<BatteryCharge> pollBatteryChargeObservable() { return Observable.<Long>interval(1, TimeUnit.MINUTES).startWith(0L).flatMap(aLong1 -> getBatteryChargeObservable(false) ).subscribeOn(Schedulers.from(mExecutor)); } private Observable<HrSession>createHrSessionListenerObservable() { return Observable.<HrSession>create(subscriber-> { final HrCallback callback=hrSession->{ subscriber.onNext(hrSession); // Check if we are done if(hrSession.getEvent()==HrEventType.HR_DONE){ subscriber.onCompleted(); } }; // Execute with our listener final Response response=WearableSDK.hrSessionListener(callback); if(response.hasError()){ subscriber.onError(new WearableError(response.getError())); }else{ Log.d(TAG,"createHrSessionListenerObservable {code=%d}",response.getCode()); } }); }
X A M P L E 2 - C O M B I N I N G Use Case: Receive HR metrics AND poll battery AND poll memory status private Observable<BatteryCharge> pollBatteryChargeObservable() { return Observable.<Long>interval(1, TimeUnit.MINUTES).startWith(0L).flatMap(aLong1 -> getBatteryChargeObservable(false) ).subscribeOn(Schedulers.from(mExecutor)); } private Observable<MemoryUsage> pollMemoryUsageObservable() { return Observable.<Long>interval(1, TimeUnit.MINUTES).startWith(0L).flatMap(aLong1 -> getMemoryUsageObservable(false) ).subscribeOn(Schedulers.from(mExecutor)); } private Observable<HrSession>createHrSessionListenerObservable() { return Observable.<HrSession>create(subscriber-> { final HrCallback callback=hrSession->{ subscriber.onNext(hrSession); // Check if we are done if(hrSession.getEvent()==HrEventType.HR_DONE){ subscriber.onCompleted(); } }; // Execute with our listener final Response response=WearableSDK.hrSessionListener(callback); if(response.hasError()){ subscriber.onError(new WearableError(response.getError())); }else{ Log.d(TAG,"createHrSessionListenerObservable {code=%d}",response.getCode()); } }); }
X A M P L E 2 - C O M B I N I N G Use Case: Receive HR metrics AND poll battery AND poll memory status private Observable<BatteryCharge> pollBatteryChargeObservable() {…} private Observable<MemoryUsage> pollMemoryUsageObservable() {…} private Observable<HrSession>createHrSessionListenerObservable() {…} public Observable<HRSessionEvent> getHrSessionListenerObservable() { /** * NB: Notice that HR Session Listener Observable is timestamped. This is * so we can determine if the device has stopped emitting events while * the Interval-Observable continues emitting. */ return Observable.<Timestamped<HrSession>, BatteryCharge, MemoryUsage, Long, HRSessionEvent>combineLatest( createHrSessionListenerObservable().timestamp(), pollBatteryChargeObservable(), pollMemoryUsageObservable(), getTickObservable(), (hrSessionTimestamped, batteryCharge, memoryUsage, aLong) -> { return HRSessionEvent.create(hrSessionTimestamped.getValue(), aLong.longValue(), hrSessionTimestamped.getTimestampMillis(), batteryCharge.getCharge(), memoryUsage.getMemoryUsage()); }) .timeout(5, TimeUnit.SECONDS) .subscribeOn(Schedulers.from(mExecutor)) .observeOn(AndroidSchedulers.mainThread()); }