RxJava on Android

26
RxJava RxAndroid VIVINT, October 2015

Transcript of RxJava on Android

Page 1: RxJava on Android

RxJava RxAndroid

VIVINT, October 2015

Page 2: RxJava on Android

Declarative vs. Imperative Programming

➤ Imperative Programming: telling the machine how to do something, and as a result what you want to happen will happen.

➤ Declarative Programming: telling the machine what you would like to happen, and let the computer figure out how to do it.

var numbers = [1,2,3,4,5] var doubled = []

for(var i = 0; i < numbers.length; i++) { var newNumber = numbers[i] * 2 doubled.push(newNumber) } console.log(doubled) //=> [2,4,6,8,10]

var numbers = [1,2,3,4,5] var total = 0

for(var i = 0; i < numbers.length; i++) { total += numbers[i] } console.log(total) //=> 15

var numbers = [1,2,3,4,5] var doubled = numbers.map(function(n) { return n * 2 }) console.log(doubled) //=> [2,4,6,8,10]

var numbers = [1,2,3,4,5]

var total = numbers.reduce(function(sum, n) { return sum + n }); console.log(total) //=> 15

Page 3: RxJava on Android

Think about spreadsheets A cell does not represent a value, but a potential stream of values.

That stream can be split into many streams, combined or fed into other streams.

There are high-order functions that can consume these streams: ‘AVERAGE’, ‘SUM’,’SUMIF’,’POWER’, etc…

Functional Reactive Programming

Savings Percent 0.2 Monthly Wages 1600Hourly Wage 10 Annual Wages 19200Hours Worked/Wk 40 Annual Savings 3840Weekly Wages 400

Savings Percent 0.4 Monthly Wages 3200Hourly Wage 20 Annual Wages 38400Hours Worked/Wk 40 Annual Savings 15360Weekly Wages 800

Page 4: RxJava on Android

What is RxJava?

➤ Observables & Subscribers

➤ High-order functions

➤ Schedulers

Page 5: RxJava on Android

Observer Contract

Observable.just(1,2,3,4,5) .subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { Log.d("Test", "sequence completed"); }

@Override public void onError(Throwable e) { Log.e("Test", "got error: " + e.getMessage()); }

@Override public void onNext(Integer integer) { Log.d("Test", "got int: " + integer); } });

The contract is very simple: onNext,onError,onCompleted

Page 6: RxJava on Android

High-order functions

➤ filter

➤ map

➤ cast

➤ buffer

➤ debounce

➤ merge

➤ zip

➤ combineLatest

➤ flatMap

A few common examples:

Page 7: RxJava on Android

Filter

Page 8: RxJava on Android

Map

Page 9: RxJava on Android

Cast

Page 10: RxJava on Android

Buffer

Page 11: RxJava on Android

Debounce

Page 12: RxJava on Android

Merge

Page 13: RxJava on Android

Zip

Page 14: RxJava on Android

CombineLatest

Page 15: RxJava on Android

FlatMap

Page 16: RxJava on Android

Schedulers

➤ computation - for computation work

➤ immediate - current thread

➤ io - IO-bound work

➤ newThread - new thread for each unit

➤ test - useful for debugging

➤ trampoline - current thread, after current work

➤ AndroidSchedulers.mainThread (RxAndroid)

Consistent with the purpose of the high-order functions, RxJava’s schedulers remove the concern of how code gets run on different threads and allows the developer to simply declare which scheduler should run which units of work.

Page 17: RxJava on Android

Example Scheduler Usage Observable .just(1) .delay(10, TimeUnit.SECONDS, Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Integer>() { @Override public void onCompleted() {

}

@Override public void onError(Throwable e) {

}

@Override public void onNext(Integer integer) { Log.d("Test", "this is on the main thread!"); } });

Page 18: RxJava on Android

RxJava + Schedulers vs AsyncTask

➤ Easier to use ➤ More effective error handling (built-in)

➤ Use of high-order functions

➤ Easily cancelable

➤ Easily retry-able ➤ Testable ➤ Greater control over concurrency

➤ AsyncTask has just 2 options, ThreadPoolExecutor or not and you can’t control what thread the onPostExecute fires on.

representativeApi.representativesByZipCode(zipCode) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .toList() .retry(2) .subscribe(onRepresentativesReceived());

A compelling RxJava Example

Page 19: RxJava on Android

RxJava on Android

➤ RxAndroid - minimum base

➤ RxLifecycle - easy lifecycle handling

➤ RxBinding - easily create observables from Android UI widgets

As of this writing, RxAndroid has had a lot of recent changes. Formerly, it contained nearly every useful thing required to build RxJava apps in Android. It has now been broken up into several constituent pieces.

Page 20: RxJava on Android

RxLifecycle

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Observable .interval(1, TimeUnit.SECONDS, Schedulers.io()) .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY)) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { Log.d("Test", "logging stuff until destroyed"); } });

}

Makes it easy to keep updates happening within safe timeframes

Page 21: RxJava on Android

RxBinding

Observable<Double> hourlyWageObservable = RxTextView.textChanges(_hourlyWage) .map(new Func1<CharSequence, Double>() { @Override public Double call(CharSequence charSequence) { try { return Double.parseDouble(charSequence.toString()); } catch (NumberFormatException e) { return 0D; } } });

Makes it easy to create Observables from Android UI widgets

Page 22: RxJava on Android

RxJava Challenges

➤ No lambdas on Android(requires Java 8)

➤ Lots of extra code, but nearly negated by solid auto-complete tools

➤ Can be overcome with retrolambda but it can be fickle

➤ Steep learning curve

➤ Easy traditional solutions can seem difficult to perform with RxJava at first

Page 25: RxJava on Android

Sample Project

➤ RxAndroid-Sample

➤ Use of RxAndroid, RxLifecycle, RxBinding

➤ Use of Retrofit with RxJava

➤ Example of converting non-RxJava code to work with RxJava

➤ More…

Page 26: RxJava on Android

Final Words

RxJava is not about writing less code or doing things that were impossible before. It’s about focusing more lines of code toward your application’s actual objectives. It helps with this by removing all the tedious, generic coding that we have to do every day: allowing the solved problems stay solved while we move on to more important things. When we can reduce the number of wrote, for-loop collection manipulation routines we can do in our sleep we can spend more time thinking about and solving the real problems.