Skip to content

Commit

Permalink
Paged list controller (#533)
Browse files Browse the repository at this point in the history
* EpoxyController that works with PagedList

This CL introduces a new class in epoxy-paging called
CachingPagingEpoxyController. This controller works with a PagedList
and caches models for each item. It still allows modifying the final
model list via an addModels API.

Fixes: 524
Test: PagedListModelCacheTest

* More docs and style fixes

* more docs & cleanup based on comments

* Rename caching paging to PagedListEpoxyController

* update sample not to add items randomly, it is confusing
  • Loading branch information
yigit authored and elihart committed Sep 21, 2018
1 parent e50f1a5 commit 0551a5c
Show file tree
Hide file tree
Showing 13 changed files with 797 additions and 89 deletions.
6 changes: 5 additions & 1 deletion blessedDeps.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ rootProject.ext.MIN_SDK_VERSION_LITHO = 15

rootProject.ext.ANDROID_SUPPORT_LIBS_VERSION = "27.1.0"
rootProject.ext.ANDROID_DATA_BINDING = "1.3.1"
rootProject.ext.ANDROID_PAGING = "1.0.0-beta1"
rootProject.ext.ANDROID_PAGING = "1.0.1"
rootProject.ext.ANDROID_ARCH_TESTING = "1.1.1"
rootProject.ext.ANDROID_TEST_RUNNER = "1.0.2"
rootProject.ext.BUTTERKNIFE_VERSION = "8.8.1"
rootProject.ext.SQUARE_JAVAPOET_VERSION = "1.11.1"
rootProject.ext.SQUARE_KOTLINPOET_VERSION = "0.7.0"
Expand All @@ -44,6 +46,8 @@ rootProject.ext.deps = [
androidDesignLibrary : "com.android.support:design:$ANDROID_SUPPORT_LIBS_VERSION",
androidRecyclerView : "com.android.support:recyclerview-v7:$ANDROID_SUPPORT_LIBS_VERSION",
androidPagingComponent: "android.arch.paging:runtime:$ANDROID_PAGING",
androidArchCoreTesting: "android.arch.core:core-testing:$ANDROID_ARCH_TESTING",
androidTestRunner : "com.android.support.test:runner:$ANDROID_TEST_RUNNER",
androidAnnotations : "com.android.support:support-annotations:$ANDROID_SUPPORT_LIBS_VERSION",
dataBindingCompiler : "com.android.databinding:compiler:$ANDROID_PLUGIN_VERSION",
dataBindingAdapters : "com.android.databinding:adapters:$ANDROID_DATA_BINDING",
Expand Down
17 changes: 10 additions & 7 deletions epoxy-paging/build.gradle
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
apply plugin: 'com.android.library'

apply plugin: 'kotlin-android'
android {
compileSdkVersion rootProject.COMPILE_SDK_VERSION

defaultConfig {
minSdkVersion rootProject.MIN_SDK_VERSION
targetSdkVersion rootProject.TARGET_SDK_VERSION
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}

dependencies {
implementation rootProject.deps.kotlin
api rootProject.deps.androidPagingComponent
api project(':epoxy-annotations')
api project(':epoxy-adapter')

compile rootProject.deps.androidPagingComponent
compile project(':epoxy-annotations')
compile project(':epoxy-adapter')
androidTestImplementation rootProject.deps.junit
androidTestImplementation rootProject.deps.androidArchCoreTesting
androidTestImplementation rootProject.deps.androidTestRunner

testCompile rootProject.deps.junit
testCompile rootProject.deps.robolectric
testCompile rootProject.deps.mockito
kaptAndroidTest project(":epoxy-processor")
}

apply from: rootProject.file('gradle/gradle-maven-push.gradle')
31 changes: 31 additions & 0 deletions epoxy-paging/src/androidTest/java/com/airbnb/epoxy/paging/Item.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.airbnb.epoxy.paging

import android.support.v7.util.DiffUtil

/**
* Dummy item for testing.
*/
data class Item(val id: Int, val value: String) {
companion object {
val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Item>() {
override fun areItemsTheSame(oldItem: Item, newItem: Item) = oldItem.id == newItem.id

override fun areContentsTheSame(oldItem: Item, newItem: Item) = oldItem == newItem
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.airbnb.epoxy.paging

import android.arch.paging.PositionalDataSource

/**
* Simple data source that works with a given list and its loading can be stopped / started.
*/
class ListDataSource<T>(
private val data: List<T>
) : PositionalDataSource<T>() {
private var pendingActions = arrayListOf<() -> Unit>()
private var running = true

private fun compute(f: () -> Unit) {
if (running) {
f()
} else {
pendingActions.add(f)
}
}

fun start() {
running = true
val pending = pendingActions
pendingActions = arrayListOf()
pending.forEach(this::compute)
}

fun stop() {
running = false
}

override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) {
compute {
callback.onResult(
data.subList(params.startPosition, Math.min(data.size, params.startPosition + params.loadSize))
)
}
}

override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<T>) {
val start = computeInitialLoadPosition(params, data.size)
val itemCnt = computeInitialLoadSize(params, start, data.size)
callback.onResult(
data.subList(start, start + itemCnt),
start,
data.size
)
}
}
Loading

0 comments on commit 0551a5c

Please sign in to comment.