Slide 1

Slide 1 text

RxBinding-kotlin @satorufujiwara

Slide 2

Slide 2 text

about me @satorufujiwara CyberAgent, Inc. AmebaFRESH!

Slide 3

Slide 3 text

AmebaFRESH! • 85% of code is written in Kotlin • kotlin-android-example • https://github.com/satorufujiwara/kotlin-android-example • 2016೥ɺKotlinͰ։ൃ͢Δํ΁ • http://qiita.com/satorufujiwara/items/871c5b7b66c7691d82a8

Slide 4

Slide 4 text

RxBiding-kotlin

Slide 5

Slide 5 text

RxBinding • RxJava binding APIs for Android UI widgets from the platform and support libraries. • by Jake Wharton • https://github.com/JakeWharton/RxBinding • Renamed from NotRxAndroid. • WidgetObservable and ViewObservable have been rolled from RxAndroid into (and improved in) it.

Slide 6

Slide 6 text

RxBinding • rxbinding • rxbinding-support-v4 • rxbinding-appcompat-v7 • rxbinding-design • rxbinding-recyclerview-v7 • rxbinding-leanback-v17

Slide 7

Slide 7 text

RxBinding-kotlin • Depends on each RxBinding’s jar. • Kotlin extension methods for each binding method.

Slide 8

Slide 8 text

RxBinding-kotlin • rxbinding-kotlin • rxbinding-support-v4-kotlin • rxbinding-appcompat-v7-kotlin • rxbinding-design-kotlin • rxbinding-recyclerview-v7-kotlin • rxbinding-leanback-v17-kotlin

Slide 9

Slide 9 text

RxBinding-kotlin • Work well with Kotlin’s lambda. • Work well with Kotlin’s extensions.

Slide 10

Slide 10 text

Basic usage in Java RxViewPager.pageSelections(viewPager)
 .subscribe(new Action1() {
 @Override
 public void call(Integer integer) {
 // call when page selected
 }
 });

Slide 11

Slide 11 text

Basic usage in Kotlin viewPager.pageSelections()
 .subscribe {
 // call when page selected
 }

Slide 12

Slide 12 text

rxbinding-support-v4-kotlin public inline fun ViewPager.pageSelections(): Observable = RxViewPager.pageSelections(this)

Slide 13

Slide 13 text

rxbinding-support-v4 public final class RxViewPager { 
 public static Observable pageSelections(ViewPager view) {
 checkNotNull(view, "view == null");
 return Observable.create(new ViewPagerPageSelectedOnSubscribe(view));
 }
 }

Slide 14

Slide 14 text

ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe {
 final ViewPager view;
 
 ViewPagerPageSelectedOnSubscribe(ViewPager view) {
 this.view = view;
 }
 
 @Override public void call(final Subscriber super Integer> subscriber) {
 checkUiThread();
 
 final ViewPager.OnPageChangeListener listener = new ViewPager.SimpleOnPageChangeListener() {
 @Override public void onPageSelected(int position) {
 if (!subscriber.isUnsubscribed()) {
 subscriber.onNext(position);
 }
 }
 };
 view.addOnPageChangeListener(listener);
 
 subscriber.add(new MainThreadSubscription() {
 @Override protected void onUnsubscribe() {
 view.removeOnPageChangeListener(listener);
 }
 });
 
 // Emit initial value.
 subscriber.onNext(view.getCurrentItem());
 }
 }

Slide 15

Slide 15 text

ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe {
 final ViewPager view;
 
 ViewPagerPageSelectedOnSubscribe(ViewPager view) {
 this.view = view;
 }
 
 @Override public void call(final Subscriber super Integer> subscriber) {
 checkUiThread();
 
 final ViewPager.OnPageChangeListener listener = new ViewPager.SimpleOnPageChangeListener() {
 @Override public void onPageSelected(int position) {
 if (!subscriber.isUnsubscribed()) {
 subscriber.onNext(position);
 }
 }
 };
 view.addOnPageChangeListener(listener);
 
 subscriber.add(new MainThreadSubscription() {
 @Override protected void onUnsubscribe() {
 view.removeOnPageChangeListener(listener);
 }
 });
 
 // Emit initial value.
 subscriber.onNext(view.getCurrentItem());
 }
 }

Slide 16

Slide 16 text

ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe {
 final ViewPager view;
 
 ViewPagerPageSelectedOnSubscribe(ViewPager view) {
 this.view = view;
 }
 
 @Override public void call(final Subscriber super Integer> subscriber) {
 checkUiThread();
 
 final ViewPager.OnPageChangeListener listener = new ViewPager.SimpleOnPageChangeListener() {
 @Override public void onPageSelected(int position) {
 if (!subscriber.isUnsubscribed()) {
 subscriber.onNext(position);
 }
 }
 };
 view.addOnPageChangeListener(listener);
 
 subscriber.add(new MainThreadSubscription() {
 @Override protected void onUnsubscribe() {
 view.removeOnPageChangeListener(listener);
 }
 });
 
 // Emit initial value.
 subscriber.onNext(view.getCurrentItem());
 }
 }

Slide 17

Slide 17 text

RxBinding’s Observable • Infinite streams • Emit initial value when subscribe

Slide 18

Slide 18 text

Basic usage in Kotlin viewPager.pageSelections()
 .subscribe {
 // call when page selected
 }

Slide 19

Slide 19 text

Use with RxLifecycle viewPager.pageSelections()
 .compose(bindToLifecycle())
 .subscribe {
 // call when page selected
 }

Slide 20

Slide 20 text

My usage of RxBiding-kotlin

Slide 21

Slide 21 text

Basic usage in Kotlin viewPager.pageSelections()
 .compose(bindToLifecycle())
 .subscribe {
 // call when page selected
 }

Slide 22

Slide 22 text

Auto loading viewPager.pageSelections()
 .filter { it > 0 && it >= adapter.count - 2 }
 .compose(bindToLifecycle())
 .subscribe {
 // call when page selected
 }

Slide 23

Slide 23 text

Auto loading class SkipUntilCompletedAction1(val doSubscribe: (T, () -> Unit) -> Unit) : Action1 {
 private var isLoading = false
 override fun call(t: T) {
 if (isLoading) return
 isLoading = true
 doSubscribe(t) { isLoading = false }
 }
 }
 
 fun Observable.subscribeWhenCompleted(doSubscribe: (t: T, completed: () -> Unit) -> Unit): Subscription =
 subscribe(SkipUntilCompletedAction1(doSubscribe))

Slide 24

Slide 24 text

Auto loading class SkipUntilCompletedAction1(val doSubscribe: (T, () -> Unit) -> Unit) : Action1 {
 private var isLoading = false
 override fun call(t: T) {
 if (isLoading) return
 isLoading = true
 doSubscribe(t) { isLoading = false }
 }
 }
 
 fun Observable.subscribeWhenCompleted(doSubscribe: (t: T, completed: () -> Unit) -> Unit): Subscription =
 subscribe(SkipUntilCompletedAction1(doSubscribe))

Slide 25

Slide 25 text

Auto loading viewPager.pageSelections()
 .filter { it > 0 && it >= adapter.count - 2 }
 .compose(bindToLifecycle())
 .subscribeWhenCompleted { list, completed ->
 getFromApi().subscribe({
 adapter.addAll(list)
 }, {
 // call when error. completed()
 }, {
 adapter.notifyDataSetChanged()
 completed()
 })
 }

Slide 26

Slide 26 text

RecyclerView’s paging class RecyclerViewPagingScrollOperator(val startPagingWith: Int = 0)
 : Observable.Operator {
 
 override fun call(child: Subscriber): Subscriber {
 return object : Subscriber(child) {
 
 override fun onCompleted() {
 child.onCompleted()
 }
 
 override fun onError(e: Throwable) {
 child.onError(e)
 }
 
 override fun onNext(scroll: RecyclerViewScrollEvent) {
 val recyclerView = scroll.view()
 val manager = recyclerView.layoutManager
 if (manager !is LinearLayoutManager) {
 child.onError(IllegalStateException("LayoutManager must be LinearLayoutManager."))
 return
 }
 val visibleCount = recyclerView.childCount
 val totalCount = manager.itemCount
 val firstVisibleCount = manager.findFirstVisibleItemPosition()
 if (visibleCount + firstVisibleCount < totalCount - startPagingWith) {
 request(1)
 return
 }
 child.onNext(RecyclerViewPagingEvent(recyclerView))
 }
 }
 }
 }
 fun Observable.mapToPagingEvents(startPagingWith: Int = 0) =
 lift(RecyclerViewPagingScrollOperator(startPagingWith))

Slide 27

Slide 27 text

Auto loading with RecyclerView recyclerView.scrollEvents()
 .mapToPagingEvents(startPagingWith = 1)
 .subscribeWhenCompleted { it, completed ->
 getFromApi() .observeOn(AndroidSchedulers.mainThread())
 .compose(bindToLifecycle())
 .subscribe({
 adapter.add(it)
 adapter.notifyDataSetChanged()
 }, {
 // call when error. completed()
 }, {
 completed()
 })
 }

Slide 28

Slide 28 text

Give ToggleButton behaviour class ToggleButtonOnSubscribe(val toggleButton: ToggleButton, val initial:Boolean)
 : Observable.OnSubscribe {
 
 private val subscriptions = CompositeSubscription()
 
 override fun call(subscriber: Subscriber) {
 toggleButton.isChecked = initial
 subscriptions.add(toggleButton.checkedChanges()
 .skip(1) // Emit initial value in RxBinding, skip it.
 .subscribe { // do something in common doSomething() subscriber.onNext(it)
 })
 subscriber.add(subscriptions)
 }
 
 }
 
 fun ToggleButton.updatedEvents(initial: Boolean) =
 Observable.create(FollowToggleButtonOnSubscribe(this, initial))

Slide 29

Slide 29 text

Give ToggleButton behaviour toggleButton.updatedEvents(true)
 .compose(bindToLifecycle())
 .subscribe {
 
 }

Slide 30

Slide 30 text

Benefit of RxBinding-kotlin • Work well with Kotlin’s lambda. • Work well with Kotlin’s extensions.

Slide 31

Slide 31 text

Benefit of RxBinding-kotlin • Work well with Kotlin’s lambda. • Work well with Kotlin’s extensions. • Method chaining. • Grouping process for the views.

Slide 32

Slide 32 text

Thank you!