[go: nahoru, domu]

Replace LoadParams with a sealed class

This CL swaps the data class LoadParams with a sealed LoadParams class.
This way, we can ensure that Append and Prepend come w/ non-null keys
while still keeping 1 method interface for cases where they only have
1 direction paging hence do not care about the load request type.

Bug: 154953944
Test: existing tests
Change-Id: I61ae333e49d514dcccc632c46e1e18759ede039e
diff --git a/paging/common/api/3.0.0-alpha01.txt b/paging/common/api/3.0.0-alpha01.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/3.0.0-alpha01.txt
+++ b/paging/common/api/3.0.0-alpha01.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/current.txt
+++ b/paging/common/api/current.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
+++ b/paging/common/api/public_plus_experimental_3.0.0-alpha01.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/api/public_plus_experimental_current.txt b/paging/common/api/public_plus_experimental_current.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/public_plus_experimental_current.txt
+++ b/paging/common/api/public_plus_experimental_current.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/api/restricted_3.0.0-alpha01.txt b/paging/common/api/restricted_3.0.0-alpha01.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/restricted_3.0.0-alpha01.txt
+++ b/paging/common/api/restricted_3.0.0-alpha01.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/api/restricted_current.txt b/paging/common/api/restricted_current.txt
index 3bcf1c4..26686b0 100644
--- a/paging/common/api/restricted_current.txt
+++ b/paging/common/api/restricted_current.txt
@@ -274,19 +274,27 @@
     property public boolean jumpingSupported;
   }
 
-  public static final class PagingSource.LoadParams<Key> {
-    ctor public PagingSource.LoadParams(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
-    method public androidx.paging.LoadType component1();
-    method public Key? component2();
-    method public int component3();
-    method public boolean component4();
-    method public int component5();
-    method public androidx.paging.PagingSource.LoadParams<Key> copy(androidx.paging.LoadType loadType, Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
+  public abstract static sealed class PagingSource.LoadParams<Key> {
+    method public abstract Key? getKey();
+    method public final int getLoadSize();
+    method public final int getPageSize();
+    method public final boolean getPlaceholdersEnabled();
+    property public abstract Key? key;
+  }
+
+  public static final class PagingSource.LoadParams.Append<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Append(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Prepend<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Prepend(Key key, int loadSize, boolean placeholdersEnabled, int pageSize);
+    method public Key getKey();
+  }
+
+  public static final class PagingSource.LoadParams.Refresh<Key> extends androidx.paging.PagingSource.LoadParams<Key> {
+    ctor public PagingSource.LoadParams.Refresh(Key? key, int loadSize, boolean placeholdersEnabled, int pageSize);
     method public Key? getKey();
-    method public int getLoadSize();
-    method public androidx.paging.LoadType getLoadType();
-    method public int getPageSize();
-    method public boolean getPlaceholdersEnabled();
   }
 
   public abstract static sealed class PagingSource.LoadResult<Key, Value> {
diff --git a/paging/common/src/main/kotlin/androidx/paging/LegacyPageFetcher.kt b/paging/common/src/main/kotlin/androidx/paging/LegacyPageFetcher.kt
index 0e6c3c5..60bc683 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LegacyPageFetcher.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LegacyPageFetcher.kt
@@ -113,8 +113,7 @@
 
         loadStateManager.setState(LoadType.PREPEND, LoadState.Loading)
 
-        val loadParams = LoadParams(
-            LoadType.PREPEND,
+        val loadParams = LoadParams.Prepend(
             key,
             config.pageSize,
             config.enablePlaceholders,
@@ -131,8 +130,7 @@
         }
 
         loadStateManager.setState(LoadType.APPEND, LoadState.Loading)
-        val loadParams = LoadParams(
-            LoadType.APPEND,
+        val loadParams = LoadParams.Append(
             key,
             config.pageSize,
             config.enablePlaceholders,
diff --git a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
index 7f5c6b1..a726700 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
@@ -22,6 +22,7 @@
 import androidx.paging.DataSource.Params
 import androidx.paging.LoadType.APPEND
 import androidx.paging.LoadType.PREPEND
+import androidx.paging.LoadType.REFRESH
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.withContext
 
@@ -39,8 +40,13 @@
     }
 
     override suspend fun load(params: LoadParams<Key>): LoadResult<Key, Value> {
+        val type = when (params) {
+            is LoadParams.Refresh -> REFRESH
+            is LoadParams.Append -> APPEND
+            is LoadParams.Prepend -> PREPEND
+        }
         val dataSourceParams = Params(
-            params.loadType,
+            type,
             params.key,
             params.loadSize,
             params.placeholdersEnabled,
@@ -52,9 +58,9 @@
                 LoadResult.Page(
                     data,
                     @Suppress("UNCHECKED_CAST")
-                    if (data.isEmpty() && params.loadType == PREPEND) null else prevKey as Key?,
+                    if (data.isEmpty() && params is LoadParams.Prepend) null else prevKey as Key?,
                     @Suppress("UNCHECKED_CAST")
-                    if (data.isEmpty() && params.loadType == APPEND) null else nextKey as Key?,
+                    if (data.isEmpty() && params is LoadParams.Append) null else nextKey as Key?,
                     itemsBefore,
                     itemsAfter
                 )
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
index da760c1..3c760b3 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -279,7 +279,7 @@
         }
     }
 
-    private fun loadParams(loadType: LoadType, key: Key?) = LoadParams(
+    private fun loadParams(loadType: LoadType, key: Key?) = LoadParams.create(
         loadType = loadType,
         key = key,
         loadSize = if (loadType == REFRESH) config.initialLoadSize else config.pageSize,
@@ -441,11 +441,11 @@
             } else {
                 val pagingState = stateLock.withLock { state.currentPagingState(lastHint) }
 
-                if (params.loadType == PREPEND && result.prevKey == null) {
+                if (params is LoadParams.Prepend && result.prevKey == null) {
                     remoteMediatorAccessor.doBoundaryCall(scope, PREPEND, pagingState)
                 }
 
-                if (params.loadType == APPEND && result.nextKey == null) {
+                if (params is LoadParams.Append && result.nextKey == null) {
                     remoteMediatorAccessor.doBoundaryCall(scope, APPEND, pagingState)
                 }
             }
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
index 02465cf..0898a0e 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
@@ -173,8 +173,7 @@
                 null -> {
                     // Compatibility codepath - perform the initial load immediately, since caller
                     // hasn't done it. We block in this case, but it's only used in the legacy path.
-                    val params = PagingSource.LoadParams(
-                        LoadType.REFRESH,
+                    val params = PagingSource.LoadParams.Refresh(
                         key,
                         config.initialLoadSizeHint,
                         config.enablePlaceholders,
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
index 0f1327d..3e5c3fb 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagingSource.kt
@@ -28,8 +28,7 @@
 @Suppress("DEPRECATION")
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 fun <Key : Any> PagedList.Config.toRefreshLoadParams(key: Key?): PagingSource.LoadParams<Key> =
-    PagingSource.LoadParams(
-        REFRESH,
+    PagingSource.LoadParams.Refresh(
         key,
         initialLoadSizeHint,
         enablePlaceholders,
@@ -78,20 +77,7 @@
     /**
      * Params for a load request on a [PagingSource] from [PagingSource.load].
      */
-    data class LoadParams<Key : Any>(
-        /**
-         * [LoadType] of this load request.
-         *
-         * May be one of the following values:
-         * * [LoadType.REFRESH] - initial load or a refresh triggered by [invalidate].
-         * * [LoadType.PREPEND] - load a page of data to be prepended to the start of the list.
-         * * [LoadType.APPEND] - load a page of data to be appended to the end of the list.
-         */
-        val loadType: LoadType,
-        /**
-         * Key for the page to be loaded.
-         */
-        val key: Key?,
+    sealed class LoadParams<Key : Any>(
         /**
          * Requested number of items to load.
          *
@@ -109,7 +95,134 @@
          * From [PagingConfig.pageSize], the configured page size.
          */
         val pageSize: Int
-    )
+    ) {
+        /**
+         * Key for the page to be loaded.
+         */
+        abstract val key: Key?
+
+        class Refresh<Key : Any>(
+            /**
+             * Key for the page to be loaded.
+             *
+             * This value might be `null` if this is the initial load and no `initialKey` is
+             * provided to the [Pager]. If this [PagingSource] was created as a replacement for
+             * a previous [PagingSource] due to refresh, this `key` is the `key` returned via
+             * [PagingSource.getRefreshKey].
+             */
+            override val key: Key?,
+            /**
+             * Requested number of items to load.
+             *
+             * Note: It is valid for [PagingSource.load] to return a [LoadResult] that has a
+             * different number of items than the requested load size.
+             */
+            loadSize: Int,
+            /**
+             * From [PagingConfig.enablePlaceholders], true if placeholders are enabled and the load
+             * request for this [LoadParams] should populate [LoadResult.Page.itemsBefore] and
+             * [LoadResult.Page.itemsAfter] if possible.
+             */
+            placeholdersEnabled: Boolean,
+            /**
+             * From [PagingConfig.pageSize], the configured page size.
+             */
+            pageSize: Int
+        ) : LoadParams<Key>(
+            loadSize = loadSize,
+            placeholdersEnabled = placeholdersEnabled,
+            pageSize = pageSize
+        )
+
+        class Append<Key : Any>(
+            /**
+             * Key for the page to be loaded.
+             */
+            override val key: Key,
+            /**
+             * Requested number of items to load.
+             *
+             * Note: It is valid for [PagingSource.load] to return a [LoadResult] that has a
+             * different number of items than the requested load size.
+             */
+            loadSize: Int,
+            /**
+             * From [PagingConfig.enablePlaceholders], true if placeholders are enabled and the load
+             * request for this [LoadParams] should populate [LoadResult.Page.itemsBefore] and
+             * [LoadResult.Page.itemsAfter] if possible.
+             */
+            placeholdersEnabled: Boolean,
+            /**
+             * From [PagingConfig.pageSize], the configured page size.
+             */
+            pageSize: Int
+        ) : LoadParams<Key>(
+            loadSize = loadSize,
+            placeholdersEnabled = placeholdersEnabled,
+            pageSize = pageSize
+        )
+
+        class Prepend<Key : Any>(
+            /**
+             * Key for the page to be loaded.
+             */
+            override val key: Key,
+            /**
+             * Requested number of items to load.
+             *
+             * Note: It is valid for [PagingSource.load] to return a [LoadResult] that has a
+             * different number of items than the requested load size.
+             */
+            loadSize: Int,
+            /**
+             * From [PagingConfig.enablePlaceholders], true if placeholders are enabled and the load
+             * request for this [LoadParams] should populate [LoadResult.Page.itemsBefore] and
+             * [LoadResult.Page.itemsAfter] if possible.
+             */
+            placeholdersEnabled: Boolean,
+            /**
+             * From [PagingConfig.pageSize], the configured page size.
+             */
+            pageSize: Int
+        ) : LoadParams<Key>(
+            loadSize = loadSize,
+            placeholdersEnabled = placeholdersEnabled,
+            pageSize = pageSize
+        )
+
+        internal companion object {
+            fun <Key : Any> create(
+                loadType: LoadType,
+                key: Key?,
+                loadSize: Int,
+                placeholdersEnabled: Boolean,
+                pageSize: Int
+            ): LoadParams<Key> = when (loadType) {
+                LoadType.REFRESH -> Refresh(
+                    key = key,
+                    loadSize = loadSize,
+                    placeholdersEnabled = placeholdersEnabled,
+                    pageSize = pageSize
+                )
+                LoadType.PREPEND -> Prepend(
+                    loadSize = loadSize,
+                    key = requireNotNull(key) {
+                        "key cannot be null for prepend"
+                    },
+                    placeholdersEnabled = placeholdersEnabled,
+                    pageSize = pageSize
+                )
+                LoadType.APPEND -> Append(
+                    loadSize = loadSize,
+                    key = requireNotNull(key) {
+                        "key cannot be null for append"
+                    },
+                    placeholdersEnabled = placeholdersEnabled,
+                    pageSize = pageSize
+                )
+            }
+        }
+    }
 
     /**
      * Result of a load request from [PagingSource.load].
diff --git a/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt b/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
index e9663ea..4850cc1 100644
--- a/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/CachingTest.kt
@@ -371,24 +371,24 @@
         private var generation = -1
 
         override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> {
-            when (params.loadType) {
-                LoadType.REFRESH -> {
+            when (params) {
+                is LoadParams.Refresh -> {
                     generation++
                     return doLoad(
                         position = params.key ?: 0,
                         size = params.loadSize
                     )
                 }
-                LoadType.PREPEND -> {
-                    val loadSize = minOf(params.key!!, params.pageSize)
+                is LoadParams.Prepend -> {
+                    val loadSize = minOf(params.key, params.pageSize)
                     return doLoad(
-                        position = params.key!! - params.loadSize,
+                        position = params.key - params.loadSize,
                         size = loadSize
                     )
                 }
-                LoadType.APPEND -> {
+                is LoadParams.Append -> {
                     return doLoad(
-                        position = params.key!!,
+                        position = params.key,
                         size = params.loadSize
                     )
                 }
diff --git a/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt b/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
index fc0c585..ae11e35 100644
--- a/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/ContiguousPagedListTest.kt
@@ -69,10 +69,10 @@
         }
 
         override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> {
-            return when (params.loadType) {
-                REFRESH -> loadInitial(params)
-                PREPEND -> loadBefore(params)
-                APPEND -> loadAfter(params)
+            return when (params) {
+                is LoadParams.Refresh -> loadInitial(params)
+                is LoadParams.Prepend -> loadBefore(params)
+                is LoadParams.Append -> loadAfter(params)
             }
         }
 
@@ -191,8 +191,7 @@
         Int
     ): Page<Int, Item> = runBlocking {
         val result = load(
-            PagingSource.LoadParams(
-                REFRESH,
+            PagingSource.LoadParams.Refresh(
                 initialKey,
                 loadSize,
                 placeholdersEnabled,
diff --git a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
index fd5b653..e40892c 100644
--- a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
@@ -19,9 +19,9 @@
 package androidx.paging
 
 import androidx.paging.LoadType.APPEND
-import androidx.paging.LoadType.REFRESH
 import androidx.paging.LoadType.PREPEND
 import androidx.paging.PagedList.Config
+import androidx.paging.PagingSource.LoadParams.Refresh
 import androidx.paging.PagingSource.LoadResult
 import androidx.paging.PagingSource.LoadResult.Page
 import androidx.testutils.TestDispatcher
@@ -42,18 +42,13 @@
         override suspend fun load(params: LoadParams<Int>): LoadResult<Int, String> {
             val key = params.key ?: 0
 
-            val start = when (params.loadType) {
-                REFRESH -> key
-                PREPEND -> key - params.loadSize
-                APPEND -> key
-            }.coerceAtLeast(0)
-
-            val end = when (params.loadType) {
-                REFRESH -> key + params.loadSize
-                PREPEND -> key
-                APPEND -> key + params.loadSize
-            }.coerceAtMost(data.size)
-
+            val (start, end) = when (params) {
+                is Refresh -> key to key + params.loadSize
+                is LoadParams.Prepend -> key - params.loadSize to key
+                is LoadParams.Append -> key to key + params.loadSize
+            }.let { (start, end) ->
+                start.coerceAtLeast(0) to end.coerceAtMost(data.size)
+            }
             return Page(
                 data = data.subList(start, end),
                 prevKey = if (start > 0) start else null,
@@ -121,8 +116,7 @@
 
         val initialResult = runBlocking {
             pagingSource.load(
-                PagingSource.LoadParams(
-                    loadType = REFRESH,
+                Refresh(
                     key = start,
                     loadSize = end - start,
                     placeholdersEnabled = config.enablePlaceholders,
diff --git a/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
index 4d01d5a..84851df 100644
--- a/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/LegacyPagingSourceTest.kt
@@ -222,7 +222,7 @@
 
         // Trigger lazy-initialization dispatch.
         val job = GlobalScope.launch {
-            pagingSource.load(PagingSource.LoadParams(REFRESH, 0, 1, false, 1))
+            pagingSource.load(PagingSource.LoadParams.Refresh(0, 1, false, 1))
         }
 
         // Assert that initialization has been scheduled on manualDispatcher, which has not been
diff --git a/paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt b/paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt
index 13dcd2b..a889369d 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PagedListTest.kt
@@ -36,8 +36,8 @@
 
         private val pagingSource = object : PagingSource<Int, String>() {
             override suspend fun load(params: LoadParams<Int>): LoadResult<Int, String> =
-                when (params.loadType) {
-                    REFRESH -> LoadResult.Page(
+                when (params) {
+                    is LoadParams.Refresh -> LoadResult.Page(
                         data = listOf("a"),
                         prevKey = null,
                         nextKey = null
@@ -115,8 +115,7 @@
     @Test
     fun defaults() = runBlocking {
         val initialPage = pagingSource.load(
-            PagingSource.LoadParams(
-                REFRESH,
+            PagingSource.LoadParams.Refresh(
                 key = null,
                 loadSize = 10,
                 placeholdersEnabled = false,
diff --git a/paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt b/paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt
index 26f78ef..4f0354f 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PagingSourceTest.kt
@@ -39,8 +39,7 @@
         enablePlaceholders: Boolean
     ): LoadResult<Key, Item> {
         return pagingSource.load(
-            LoadParams(
-                LoadType.REFRESH,
+            LoadParams.Refresh(
                 key,
                 initialLoadSize,
                 enablePlaceholders,
@@ -62,7 +61,7 @@
 
             // Verify error is propagated correctly.
             pagingSource.enqueueError()
-            val errorParams = LoadParams(LoadType.REFRESH, key, 10, false, 10)
+            val errorParams = LoadParams.Refresh(key, 10, false, 10)
             assertFailsWith<CustomException> {
                 pagingSource.load(errorParams)
             }
@@ -194,7 +193,7 @@
 
         runBlocking {
             val key = ITEMS_BY_NAME_ID[5].key()
-            val params = LoadParams(LoadType.PREPEND, key, 5, false, 5)
+            val params = LoadParams.Prepend(key, 5, false, 5)
             val observed = (dataSource.load(params) as LoadResult.Page).data
 
             assertEquals(ITEMS_BY_NAME_ID.subList(0, 5), observed)
@@ -202,7 +201,7 @@
             // Verify error is propagated correctly.
             dataSource.enqueueError()
             assertFailsWith<CustomException> {
-                val errorParams = LoadParams(LoadType.PREPEND, key, 5, false, 5)
+                val errorParams = LoadParams.Prepend(key, 5, false, 5)
                 dataSource.load(errorParams)
             }
         }
@@ -214,7 +213,7 @@
 
         runBlocking {
             val key = ITEMS_BY_NAME_ID[5].key()
-            val params = LoadParams(LoadType.APPEND, key, 5, false, 5)
+            val params = LoadParams.Append(key, 5, false, 5)
             val observed = (dataSource.load(params) as LoadResult.Page).data
 
             assertEquals(ITEMS_BY_NAME_ID.subList(6, 11), observed)
@@ -222,7 +221,7 @@
             // Verify error is propagated correctly.
             dataSource.enqueueError()
             assertFailsWith<CustomException> {
-                val errorParams = LoadParams(LoadType.APPEND, key, 5, false, 5)
+                val errorParams = LoadParams.Append(key, 5, false, 5)
                 dataSource.load(errorParams)
             }
         }
@@ -265,10 +264,10 @@
         }
 
         override suspend fun load(params: LoadParams<Key>): LoadResult<Key, Item> {
-            return when (params.loadType) {
-                LoadType.REFRESH -> loadInitial(params)
-                LoadType.PREPEND -> loadBefore(params)
-                LoadType.APPEND -> loadAfter(params)
+            return when (params) {
+                is LoadParams.Refresh -> loadInitial(params)
+                is LoadParams.Prepend -> loadBefore(params)
+                is LoadParams.Append -> loadAfter(params)
             }
         }
 
diff --git a/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingSourceTest.kt b/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingSourceTest.kt
index ee80101..742be97 100644
--- a/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingSourceTest.kt
+++ b/paging/guava/src/test/java/androidx/paging/ListenableFuturePagingSourceTest.kt
@@ -60,14 +60,14 @@
 
     @Test
     fun basic() = runBlocking {
-        val params = LoadParams(LoadType.REFRESH, 0, 2, false, 2)
+        val params = LoadParams.Refresh(0, 2, false, 2)
         assertEquals(pagingSource.load(params), listenableFuturePagingSource.load(params))
     }
 
     @Test
     fun error() {
         runBlocking {
-            val params = LoadParams<Int>(LoadType.REFRESH, null, 2, false, 2)
+            val params = LoadParams.Refresh<Int>(null, 2, false, 2)
             assertFailsWith<NullPointerException> { pagingSource.load(params) }
             assertFailsWith<NullPointerException> { listenableFuturePagingSource.load(params) }
         }
@@ -76,7 +76,7 @@
     @Test
     fun errorWrapped() {
         runBlocking {
-            val params = LoadParams(LoadType.REFRESH, -1, 2, false, 2)
+            val params = LoadParams.Refresh(-1, 2, false, 2)
             assertFailsWith<IllegalArgumentException> { pagingSource.load(params) }
             assertFailsWith<IllegalArgumentException> { listenableFuturePagingSource.load(params) }
         }
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/ItemDataSource.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/ItemDataSource.kt
index 683f58c..bff3ebf 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/ItemDataSource.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/custom/ItemDataSource.kt
@@ -37,22 +37,22 @@
     override fun getRefreshKey(state: PagingState<Int, Item>): Int? = state.anchorPosition
 
     override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> =
-        when (params.loadType) {
-            LoadType.REFRESH ->
+        when (params) {
+            is LoadParams.Refresh ->
                 loadInternal(
                     position = ((params.key ?: 0) - params.loadSize / 2).coerceAtLeast(0),
                     loadSize = params.loadSize
                 )
-            LoadType.PREPEND -> {
-                val loadSize = minOf(params.key!!, params.pageSize)
+            is LoadParams.Prepend -> {
+                val loadSize = minOf(params.key, params.pageSize)
                 loadInternal(
-                    position = params.key!! - loadSize,
+                    position = params.key - loadSize,
                     loadSize = loadSize
                 )
             }
-            LoadType.APPEND ->
+            is LoadParams.Append ->
                 loadInternal(
-                    position = params.key!!,
+                    position = params.key,
                     loadSize = params.loadSize
                 )
         }
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/ItemPagingSource.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/ItemPagingSource.kt
index e393e40..da89bf0 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/ItemPagingSource.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3/ItemPagingSource.kt
@@ -37,22 +37,22 @@
     override fun getRefreshKey(state: PagingState<Int, Item>): Int? = state.anchorPosition
 
     override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Item> =
-        when (params.loadType) {
-            LoadType.REFRESH ->
+        when (params) {
+            is LoadParams.Refresh ->
                 loadInternal(
                     position = ((params.key ?: 0) - params.loadSize / 2).coerceAtLeast(0),
                     loadSize = params.loadSize
                 )
-            LoadType.PREPEND -> {
-                val loadSize = minOf(params.key!!, params.pageSize)
+            is LoadParams.Prepend -> {
+                val loadSize = minOf(params.key, params.pageSize)
                 loadInternal(
-                    position = params.key!! - loadSize,
+                    position = params.key - loadSize,
                     loadSize = loadSize
                 )
             }
-            LoadType.APPEND ->
+            is LoadParams.Append ->
                 loadInternal(
-                    position = params.key!!,
+                    position = params.key,
                     loadSize = params.loadSize
                 )
         }
diff --git a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt
index fa14ce4..13b49ac 100644
--- a/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt
+++ b/paging/integration-tests/testapp/src/main/java/androidx/paging/integration/testapp/v3room/V3RemoteMediator.kt
@@ -38,20 +38,22 @@
 
         // TODO: Move this to be a more fully featured sample which demonstrated key translation
         //  between two types of PagingSources where the keys do not map 1:1.
-        val key = when (loadType) {
-            LoadType.REFRESH -> 0
-            LoadType.PREPEND -> throw IllegalStateException()
-            LoadType.APPEND -> state.pages.lastOrNull()?.nextKey ?: 0
-        }
-        val result = networkSource.load(
-            PagingSource.LoadParams(
-                loadType = loadType,
-                key = key,
+        val loadParams = when (loadType) {
+            LoadType.REFRESH -> PagingSource.LoadParams.Refresh(
+                key = 0,
                 loadSize = 10,
                 placeholdersEnabled = false,
                 pageSize = 10
             )
-        )
+            LoadType.PREPEND -> throw IllegalStateException()
+            LoadType.APPEND -> PagingSource.LoadParams.Append(
+                key = state.pages.lastOrNull()?.nextKey ?: 0,
+                loadSize = 10,
+                placeholdersEnabled = false,
+                pageSize = 10
+            )
+        }
+        val result = networkSource.load(loadParams)
 
         return when (result) {
             is PagingSource.LoadResult.Page -> {
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
index 0dca678..29a14ff 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListBuilderTest.kt
@@ -97,8 +97,8 @@
         }
 
         private inner class MockPagingSource : PagingSource<Int, String>() {
-            override suspend fun load(params: LoadParams<Int>) = when (params.loadType) {
-                REFRESH -> loadInitial(params)
+            override suspend fun load(params: LoadParams<Int>) = when (params) {
+                is LoadParams.Refresh -> loadInitial(params)
                 else -> loadRange()
             }
 
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt b/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
index 6c99a64..231cb21 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
@@ -28,7 +28,7 @@
     private val data: List<Value>
 ) : PagingSource<Any, Value>() {
     override suspend fun load(params: LoadParams<Any>): LoadResult<Any, Value> {
-        if (params.loadType == LoadType.REFRESH) {
+        if (params is LoadParams.Refresh) {
             return Page(
                 data = data,
                 prevKey = null,
diff --git a/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt b/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
index 62ecf76..6197eb1 100644
--- a/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
+++ b/paging/rxjava2/src/test/java/androidx/paging/RxPagedListBuilderTest.kt
@@ -61,8 +61,8 @@
         }
 
         private inner class MockPagingSource : PagingSource<Int, String>() {
-            override suspend fun load(params: LoadParams<Int>) = when (params.loadType) {
-                LoadType.REFRESH -> loadInitial(params)
+            override suspend fun load(params: LoadParams<Int>) = when (params) {
+                is LoadParams.Refresh -> loadInitial(params)
                 else -> loadRange()
             }
 
diff --git a/paging/rxjava2/src/test/java/androidx/paging/RxPagingSourceTest.kt b/paging/rxjava2/src/test/java/androidx/paging/RxPagingSourceTest.kt
index a42d94d..3110503 100644
--- a/paging/rxjava2/src/test/java/androidx/paging/RxPagingSourceTest.kt
+++ b/paging/rxjava2/src/test/java/androidx/paging/RxPagingSourceTest.kt
@@ -52,14 +52,14 @@
 
     @Test
     fun basic() = runBlocking {
-        val params = PagingSource.LoadParams(LoadType.REFRESH, 0, 2, false, 2)
+        val params = PagingSource.LoadParams.Refresh(0, 2, false, 2)
         assertEquals(pagingSource.load(params), rxPagingSource.load(params))
     }
 
     @Test
     fun error() {
         runBlocking {
-            val params = PagingSource.LoadParams<Int>(LoadType.REFRESH, null, 2, false, 2)
+            val params = PagingSource.LoadParams.Refresh<Int>(null, 2, false, 2)
             assertFailsWith<NullPointerException> { pagingSource.load(params) }
             assertFailsWith<NullPointerException> { rxPagingSource.load(params) }
         }
diff --git a/testutils/testutils-paging/src/main/java/androidx/paging/TestPagingSource.kt b/testutils/testutils-paging/src/main/java/androidx/paging/TestPagingSource.kt
index f87f132..b094a61 100644
--- a/testutils/testutils-paging/src/main/java/androidx/paging/TestPagingSource.kt
+++ b/testutils/testutils-paging/src/main/java/androidx/paging/TestPagingSource.kt
@@ -43,8 +43,9 @@
     override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Int> {
         val key = params.key ?: 0
 
-        val start = if (params.loadType == LoadType.PREPEND) key - params.loadSize + 1 else key
-        val end = if (params.loadType == LoadType.PREPEND) key + 1 else key + params.loadSize
+        val isPrepend = params is LoadParams.Prepend
+        val start = if (isPrepend) key - params.loadSize + 1 else key
+        val end = if (isPrepend) key + 1 else key + params.loadSize
 
         // This delay allows tests running withing DelayController APIs to control the order of
         // execution of events.