Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxBinding-kotlin #Kotlin_Sansan

RxBinding-kotlin #Kotlin_Sansan

AndroidでKotlin勉強会 @ Sansan で発表したスライドです。
http://connpass.com/event/22189/

B0f8177e3259f29952640f98bf795965?s=128

satorufujiwara

January 16, 2016
Tweet

More Decks by satorufujiwara

Other Decks in Programming

Transcript

  1. RxBinding-kotlin @satorufujiwara

  2. about me @satorufujiwara CyberAgent, Inc. AmebaFRESH!

  3. 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
  4. RxBiding-kotlin

  5. 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.
  6. RxBinding • rxbinding • rxbinding-support-v4 • rxbinding-appcompat-v7 • rxbinding-design •

    rxbinding-recyclerview-v7 • rxbinding-leanback-v17
  7. RxBinding-kotlin • Depends on each RxBinding’s jar. • Kotlin extension

    methods for each binding method.
  8. RxBinding-kotlin • rxbinding-kotlin • rxbinding-support-v4-kotlin • rxbinding-appcompat-v7-kotlin • rxbinding-design-kotlin •

    rxbinding-recyclerview-v7-kotlin • rxbinding-leanback-v17-kotlin
  9. RxBinding-kotlin • Work well with Kotlin’s lambda. • Work well

    with Kotlin’s extensions.
  10. Basic usage in Java RxViewPager.pageSelections(viewPager)
 .subscribe(new Action1<Integer>() {
 @Override
 public

    void call(Integer integer) {
 // call when page selected
 }
 });
  11. Basic usage in Kotlin viewPager.pageSelections()
 .subscribe {
 // call when

    page selected
 }
  12. rxbinding-support-v4-kotlin public inline fun ViewPager.pageSelections(): Observable<Int> = RxViewPager.pageSelections(this)

  13. rxbinding-support-v4 public final class RxViewPager { 
 public static Observable<Integer>

    pageSelections(ViewPager view) {
 checkNotNull(view, "view == null");
 return Observable.create(new ViewPagerPageSelectedOnSubscribe(view));
 }
 }
  14. ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe<Integer> {
 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());
 }
 }
  15. ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe<Integer> {
 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());
 }
 }
  16. ViewPagerPageSelectedOnSubscribe final class ViewPagerPageSelectedOnSubscribe implements Observable.OnSubscribe<Integer> {
 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());
 }
 }
  17. RxBinding’s Observable • Infinite streams • Emit initial value when

    subscribe
  18. Basic usage in Kotlin viewPager.pageSelections()
 .subscribe {
 // call when

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

    page selected
 }
  20. My usage of RxBiding-kotlin

  21. Basic usage in Kotlin viewPager.pageSelections()
 .compose(bindToLifecycle<Int>())
 .subscribe {
 // call

    when page selected
 }
  22. Auto loading viewPager.pageSelections()
 .filter { it > 0 && it

    >= adapter.count - 2 }
 .compose(bindToLifecycle<Int>())
 .subscribe {
 // call when page selected
 }
  23. Auto loading class SkipUntilCompletedAction1<T>(val doSubscribe: (T, () -> Unit) ->

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

    Unit) : Action1<T> {
 private var isLoading = false
 override fun call(t: T) {
 if (isLoading) return
 isLoading = true
 doSubscribe(t) { isLoading = false }
 }
 }
 
 fun <T>Observable<T>.subscribeWhenCompleted(doSubscribe: (t: T, completed: () -> Unit) -> Unit): Subscription =
 subscribe(SkipUntilCompletedAction1(doSubscribe))
  25. Auto loading viewPager.pageSelections()
 .filter { it > 0 && it

    >= adapter.count - 2 }
 .compose(bindToLifecycle<Int>())
 .subscribeWhenCompleted { list, completed ->
 getFromApi().subscribe({
 adapter.addAll(list)
 }, {
 // call when error. completed()
 }, {
 adapter.notifyDataSetChanged()
 completed()
 })
 }
  26. RecyclerView’s paging class RecyclerViewPagingScrollOperator(val startPagingWith: Int = 0)
 : Observable.Operator<RecyclerViewPagingEvent,

    RecyclerViewScrollEvent> {
 
 override fun call(child: Subscriber<in RecyclerViewPagingEvent>): Subscriber<in RecyclerViewScrollEvent> {
 return object : Subscriber<RecyclerViewScrollEvent>(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<RecyclerViewScrollEvent>.mapToPagingEvents(startPagingWith: Int = 0) =
 lift(RecyclerViewPagingScrollOperator(startPagingWith))
  27. Auto loading with RecyclerView recyclerView.scrollEvents()
 .mapToPagingEvents(startPagingWith = 1)
 .subscribeWhenCompleted {

    it, completed ->
 getFromApi() .observeOn(AndroidSchedulers.mainThread())
 .compose(bindToLifecycle<Channel>())
 .subscribe({
 adapter.add(it)
 adapter.notifyDataSetChanged()
 }, {
 // call when error. completed()
 }, {
 completed()
 })
 }
  28. Give ToggleButton behaviour class ToggleButtonOnSubscribe(val toggleButton: ToggleButton, val initial:Boolean)
 :

    Observable.OnSubscribe<Boolean> {
 
 private val subscriptions = CompositeSubscription()
 
 override fun call(subscriber: Subscriber<in Boolean>) {
 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))
  29. Give ToggleButton behaviour toggleButton.updatedEvents(true)
 .compose(bindToLifecycle<Boolean>())
 .subscribe {
 
 }

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

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

    Work well with Kotlin’s extensions. • Method chaining. • Grouping process for the views.
  32. Thank you!