recyclerview-bindings icon indicating copy to clipboard operation
recyclerview-bindings copied to clipboard

RecyclerViewBindings provides a wrapper class RecyclerViewScrollCallback which can be used to add Scroll to Bottom and Pull to Refresh capability to your RecyclerView. You can make use of DataBinding...

RecyclerView Bindings

RecyclerViewBindings provides a wrapper class RecyclerViewScrollCallback which can be used to add Scroll to Bottom (Endless Scroll) and Pull to Refresh capability to your RecyclerView. You can make use of DataBinding to bind it via XML.

How to Use

val callback = RecyclerViewScrollCallback
        .Builder(visibleThreshold, recyclerView.layoutManager)
        .resetLoadingState(resetLoadingState)
        .onScrolledToBottom(onScrolledToBottom)
        .build()

recyclerView.clearOnScrollListeners()
recyclerView.addOnScrollListener(callback)

How to Bind

In your Gradle

    dataBinding {
        enabled = true
    }

In your BindingAdapter

/**
 * @param recyclerView  RecyclerView to bind to RecyclerViewScrollCallback
 * @param visibleThreshold  The minimum number of items to have below your current scroll position before loading more.
 * @param resetLoadingState  Reset endless scroll listener when performing a new search
 * @param onScrolledToBottom    OnScrolledListener for RecyclerView scrolled
 */
@BindingAdapter(value = *arrayOf("visibleThreshold", "resetLoadingState", "onScrolledToBottom"), requireAll = false)
fun setRecyclerViewScrollCallback(recyclerView: RecyclerView, visibleThreshold: Int, resetLoadingState: Boolean,
                                  onScrolledToBottom: RecyclerViewScrollCallback.OnScrolledListener) {

    ... // add addOnScrollListener to RecyclerView using OnScrolledListener as above
}

/**
 * @param swipeRefreshLayout Bind swipeRefreshLayout with OnRefreshListener
 * @param onRefresh Listener for onRefresh when swiped
 */
@BindingAdapter("onPulledToRefresh")
fun setOnSwipeRefreshListener(swipeRefreshLayout: SwipeRefreshLayout, onPulledToRefresh: Runnable) {
    swipeRefreshLayout.setOnRefreshListener { onPulledToRefresh.run() }
}

In your XML file

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/srl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    bind:onPulledToRefresh="@{() -> presenter.initialize()}">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/grey"
        app:layoutManager="android.support.v7.widget.LinearLayoutManager"
        bind:onScrolledToBottom="@{(page) -> presenter.onLoadMore(page)}"
        bind:resetLoadingState="@{model.resetLoadingState}"
        bind:spaceItemDecoration="@{@dimen/space_very_low}"
        bind:visibleThreshold="@{model.visibleThreshold}"
        tools:listitem="@layout/item_main" />

</android.support.v4.widget.SwipeRefreshLayout>

Pagination using RxJava (using Subjects)

/**
 * initialize all resources
 * set current page to 1
 * create paginator and subscribe to events
 */
override fun initialize() {
    currentPage = 1                                         // set page = 1
    paginator = PublishProcessor.create()                   // create PublishProcessor

    val d = paginator.onBackpressureDrop()
            .filter { !loading }                            // return if it is still loading
            .doOnNext { loading = view.showProgress() }     // loading = true
            .concatMap { contract.getUsersFromServer(it) }  // API call
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                loading = view.hideProgress()               // loading = false
                view.showItems(it)                          // show items
                currentPage++                               // increment page
            }, {
                loading = view.hideProgress()               // loading = false
                view.showError(it.localizedMessage)         // show error
            })

    disposables.add(d)

    onLoadMore(currentPage)
}

/**
 * called when list is scrolled to its bottom
 * @param page current page (not used)
 */
override fun onLoadMore(page: Int) {
    paginator.onNext(currentPage)                           // increment page if not loading
}

Library used

Add Android Support Design, RxJava and RxAndroid dependency to your gradle file.

dependencies {
    compile 'com.android.support:design:{latest_version}'
    compile 'io.reactivex.rxjava2:rxandroid:{latest_version}'
    compile 'io.reactivex.rxjava2:rxjava:{latest_version}'
}

Also try

Reference