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/

satorufujiwara

January 16, 2016
Tweet

More Decks by satorufujiwara

Other Decks in Programming

Transcript

  1. 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
  2. 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.
  3. rxbinding-support-v4 public final class RxViewPager { 
 public static Observable<Integer>

    pageSelections(ViewPager view) {
 checkNotNull(view, "view == null");
 return Observable.create(new ViewPagerPageSelectedOnSubscribe(view));
 }
 }
  4. 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());
 }
 }
  5. 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());
 }
 }
  6. 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());
 }
 }
  7. Auto loading viewPager.pageSelections()
 .filter { it > 0 && it

    >= adapter.count - 2 }
 .compose(bindToLifecycle<Int>())
 .subscribe {
 // call when page selected
 }
  8. 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))
  9. 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))
  10. 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()
 })
 }
  11. 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))
  12. 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()
 })
 }
  13. 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))
  14. Benefit of RxBinding-kotlin • Work well with Kotlin’s lambda. •

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