Converting `paging` related files in `room-runtime` from Java to Kotlin.
Test: LimitOffsetDataSourceTest.java
Bug: 206859668
Relnote: Converting `paging` related files in `room-runtime` from Java to Kotlin.
Change-Id: I82fc81469540315dbe4865ccde68396a4339dfd9
diff --git a/room/room-runtime/api/restricted_current.ignore b/room/room-runtime/api/restricted_current.ignore
index e6a9bf9..a566a8f 100644
--- a/room/room-runtime/api/restricted_current.ignore
+++ b/room/room-runtime/api/restricted_current.ignore
@@ -1,3 +1,7 @@
// Baseline format: 1.0
+ChangedType: androidx.room.paging.LimitOffsetDataSource#convertRows(android.database.Cursor):
+ Method androidx.room.paging.LimitOffsetDataSource.convertRows has changed return type from java.util.List<T!> to java.util.List<T>
+
+
RemovedClass: androidx.room.util.CopyLock:
Removed class androidx.room.util.CopyLock
diff --git a/room/room-runtime/api/restricted_current.txt b/room/room-runtime/api/restricted_current.txt
index 8f29006..24bc4fb 100644
--- a/room/room-runtime/api/restricted_current.txt
+++ b/room/room-runtime/api/restricted_current.txt
@@ -236,13 +236,14 @@
package androidx.room.paging {
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class LimitOffsetDataSource<T> extends androidx.paging.PositionalDataSource<T> {
- ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase, androidx.sqlite.db.SupportSQLiteQuery, boolean, java.lang.String!...);
- ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase, androidx.sqlite.db.SupportSQLiteQuery, boolean, boolean, java.lang.String!...);
- ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase, androidx.room.RoomSQLiteQuery, boolean, java.lang.String!...);
- ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase, androidx.room.RoomSQLiteQuery, boolean, boolean, java.lang.String!...);
- method protected abstract java.util.List<T!> convertRows(android.database.Cursor);
- method public void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams, androidx.paging.PositionalDataSource.LoadInitialCallback<T!>);
- method public void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams, androidx.paging.PositionalDataSource.LoadRangeCallback<T!>);
+ ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase db, androidx.room.RoomSQLiteQuery sourceQuery, boolean inTransaction, boolean registerObserverImmediately, java.lang.String... tables);
+ ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase db, androidx.sqlite.db.SupportSQLiteQuery query, boolean inTransaction, java.lang.String... tables);
+ ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase db, androidx.sqlite.db.SupportSQLiteQuery query, boolean inTransaction, boolean registerObserverImmediately, java.lang.String... tables);
+ ctor protected LimitOffsetDataSource(androidx.room.RoomDatabase db, androidx.room.RoomSQLiteQuery query, boolean inTransaction, java.lang.String... tables);
+ method protected abstract java.util.List<T> convertRows(android.database.Cursor cursor);
+ method public void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams params, androidx.paging.PositionalDataSource.LoadInitialCallback<T> callback);
+ method public void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams params, androidx.paging.PositionalDataSource.LoadRangeCallback<T> callback);
+ property public boolean isInvalid;
}
}
diff --git a/room/room-runtime/build.gradle b/room/room-runtime/build.gradle
index 0cdeecd..3e43c71 100644
--- a/room/room-runtime/build.gradle
+++ b/room/room-runtime/build.gradle
@@ -36,7 +36,7 @@
api(project(":sqlite:sqlite-framework"))
api(project(":sqlite:sqlite"))
implementation("androidx.arch.core:core-runtime:2.0.1")
- compileOnly("androidx.paging:paging-common:2.0.0")
+ compileOnly("androidx.paging:paging-common:3.1.0")
compileOnly("androidx.lifecycle:lifecycle-livedata-core:2.0.0")
implementation("androidx.annotation:annotation-experimental:1.1.0-rc01")
compileOnly libs.kotlinStdlib // Due to :annotation-experimental
diff --git a/room/room-runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.kt b/room/room-runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.kt
index 81ba417..f1203ae 100644
--- a/room/room-runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.kt
+++ b/room/room-runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.kt
@@ -13,104 +13,88 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+@file:Suppress("DEPRECATION")
-package androidx.room.paging;
+package androidx.room.paging
-import android.database.Cursor;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.room.InvalidationTracker;
-import androidx.room.RoomDatabase;
-import androidx.room.RoomSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
+import android.database.Cursor
+import androidx.annotation.RestrictTo
+import androidx.paging.PositionalDataSource
+import androidx.room.InvalidationTracker
+import androidx.room.RoomDatabase
+import androidx.room.RoomSQLiteQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import java.util.concurrent.atomic.AtomicBoolean
/**
* A simple data source implementation that uses Limit & Offset to page the query.
- * <p>
+ *
* This is NOT the most efficient way to do paging on SQLite. It is
- * <a href="http://www.sqlite.org/cvstrac/wiki?p=ScrollingCursor">recommended</a> to use an indexed
+ * [recommended](http://www.sqlite.org/cvstrac/wiki?p=ScrollingCursor) to use an indexed
* ORDER BY statement but that requires a more complex API. This solution is technically equal to
- * receiving a {@link Cursor} from a large query but avoids the need to manually manage it, and
+ * receiving a [Cursor] from a large query but avoids the need to manually manage it, and
* never returns inconsistent data if it is invalidated.
*
- * This class is used for both Paging2 and Pagin3 (via its compat API). When used with Paging3,
+ * This class is used for both Paging2 and Paging3 (via its compat API). When used with Paging3,
* it does lazy registration for observers to be suitable for initialization on the main thread
* whereas in Paging2, it will register observer eagerly to obey Paging2's strict Data Source
* rules. (Paging2 does not let data source to possibly return invalidated data).
*
- * @param <T> Data type returned by the data source.
+ * @property <T> Data type returned by the data source.
*
* @hide
*/
-@SuppressWarnings("deprecation")
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-public abstract class LimitOffsetDataSource<T> extends androidx.paging.PositionalDataSource<T> {
- private final RoomSQLiteQuery mSourceQuery;
- private final String mCountQuery;
- private final String mLimitOffsetQuery;
- private final RoomDatabase mDb;
- @SuppressWarnings("FieldCanBeLocal")
- private final InvalidationTracker.Observer mObserver;
- private final boolean mInTransaction;
- private final AtomicBoolean mRegisteredObserver = new AtomicBoolean(false);
+abstract class LimitOffsetDataSource<T : Any> protected constructor(
+ private val db: RoomDatabase,
+ private val sourceQuery: RoomSQLiteQuery,
+ private val inTransaction: Boolean,
+ registerObserverImmediately: Boolean,
+ vararg tables: String
+) : PositionalDataSource<T>() {
+ private val countQuery = "SELECT COUNT(*) FROM ( " + sourceQuery.sql + " )"
+ private val limitOffsetQuery = "SELECT * FROM ( " + sourceQuery.sql + " ) LIMIT ? OFFSET ?"
+ private val observer: InvalidationTracker.Observer
+ private val registeredObserver = AtomicBoolean(false)
- protected LimitOffsetDataSource(@NonNull RoomDatabase db,
- @NonNull SupportSQLiteQuery query,
- boolean inTransaction,
- @NonNull
- String... tables) {
- this(db, RoomSQLiteQuery.copyFrom(query), inTransaction, tables);
- }
+ protected constructor(
+ db: RoomDatabase,
+ query: SupportSQLiteQuery,
+ inTransaction: Boolean,
+ vararg tables: String
+ ) : this(db, RoomSQLiteQuery.copyFrom(query), inTransaction, *tables)
- protected LimitOffsetDataSource(
- @NonNull RoomDatabase db,
- @NonNull SupportSQLiteQuery query,
- boolean inTransaction,
- boolean registerObserverImmediately,
- @NonNull String... tables) {
- this(db, RoomSQLiteQuery.copyFrom(query), inTransaction, registerObserverImmediately,
- tables);
- }
+ protected constructor(
+ db: RoomDatabase,
+ query: SupportSQLiteQuery,
+ inTransaction: Boolean,
+ registerObserverImmediately: Boolean,
+ vararg tables: String
+ ) : this(
+ db, RoomSQLiteQuery.copyFrom(query), inTransaction, registerObserverImmediately, *tables
+ )
- protected LimitOffsetDataSource(
- @NonNull RoomDatabase db,
- @NonNull RoomSQLiteQuery query,
- boolean inTransaction,
- @NonNull String... tables) {
- this(db, query, inTransaction, true /*register registerObserverImmediately*/, tables);
- }
+ protected constructor(
+ db: RoomDatabase,
+ query: RoomSQLiteQuery,
+ inTransaction: Boolean,
+ vararg tables: String
+ ) : this(db, query, inTransaction, true, *tables)
- protected LimitOffsetDataSource(
- @NonNull RoomDatabase db,
- @NonNull RoomSQLiteQuery query,
- boolean inTransaction,
- boolean registerObserverImmediately,
- @NonNull String... tables) {
- mDb = db;
- mSourceQuery = query;
- mInTransaction = inTransaction;
- mCountQuery = "SELECT COUNT(*) FROM ( " + mSourceQuery.getSql() + " )";
- mLimitOffsetQuery = "SELECT * FROM ( " + mSourceQuery.getSql() + " ) LIMIT ? OFFSET ?";
- mObserver = new InvalidationTracker.Observer(tables) {
- @Override
- public void onInvalidated(@NonNull Set<String> tables) {
- invalidate();
+ init {
+ observer = object : InvalidationTracker.Observer(tables) {
+ override fun onInvalidated(tables: Set<String>) {
+ invalidate()
}
- };
+ }
if (registerObserverImmediately) {
- registerObserverIfNecessary();
+ registerObserverIfNecessary()
}
}
- private void registerObserverIfNecessary() {
- if (mRegisteredObserver.compareAndSet(false, true)) {
- mDb.getInvalidationTracker().addWeakObserver(mObserver);
+ private fun registerObserverIfNecessary() {
+ if (registeredObserver.compareAndSet(false, true)) {
+ db.invalidationTracker.addWeakObserver(observer)
}
}
@@ -119,76 +103,63 @@
*
* @hide
*/
- @SuppressWarnings("WeakerAccess")
- public int countItems() {
- registerObserverIfNecessary();
- final RoomSQLiteQuery sqLiteQuery = RoomSQLiteQuery.acquire(mCountQuery,
- mSourceQuery.getArgCount());
- sqLiteQuery.copyArgumentsFrom(mSourceQuery);
- Cursor cursor = mDb.query(sqLiteQuery);
- try {
+ fun countItems(): Int {
+ registerObserverIfNecessary()
+ val sqLiteQuery = RoomSQLiteQuery.acquire(
+ countQuery,
+ sourceQuery.argCount
+ )
+ sqLiteQuery.copyArgumentsFrom(sourceQuery)
+ val cursor = db.query(sqLiteQuery)
+ return try {
if (cursor.moveToFirst()) {
- return cursor.getInt(0);
- }
- return 0;
+ cursor.getInt(0)
+ } else 0
} finally {
- cursor.close();
- sqLiteQuery.release();
+ cursor.close()
+ sqLiteQuery.release()
}
}
- @Override
- public boolean isInvalid() {
- registerObserverIfNecessary();
- mDb.getInvalidationTracker().refreshVersionsSync();
- return super.isInvalid();
+ override val isInvalid: Boolean
+ get() {
+ registerObserverIfNecessary()
+ db.invalidationTracker.refreshVersionsSync()
+ return super.isInvalid
}
- @NonNull
- @SuppressWarnings("WeakerAccess")
- protected abstract List<T> convertRows(@NonNull Cursor cursor);
+ protected abstract fun convertRows(cursor: Cursor): List<T>
- @SuppressWarnings("deprecation")
- @Override
- public void loadInitial(@NonNull LoadInitialParams params,
- @NonNull LoadInitialCallback<T> callback) {
- registerObserverIfNecessary();
- List<T> list = Collections.emptyList();
- int totalCount;
- int firstLoadPosition = 0;
- RoomSQLiteQuery sqLiteQuery = null;
- Cursor cursor = null;
- mDb.beginTransaction();
+ @Suppress("deprecation")
+ override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<T>) {
+ registerObserverIfNecessary()
+ val onResultCaller: () -> Unit
+ db.beginTransaction()
try {
- totalCount = countItems();
+ val totalCount = countItems()
if (totalCount != 0) {
// bound the size requested, based on known count
- firstLoadPosition = computeInitialLoadPosition(params, totalCount);
- int firstLoadSize = computeInitialLoadSize(params, firstLoadPosition, totalCount);
-
- sqLiteQuery = getSQLiteQuery(firstLoadPosition, firstLoadSize);
- cursor = mDb.query(sqLiteQuery);
- List<T> rows = convertRows(cursor);
- mDb.setTransactionSuccessful();
- list = rows;
+ val firstLoadPosition = computeInitialLoadPosition(params, totalCount)
+ val firstLoadSize = computeInitialLoadSize(params, firstLoadPosition, totalCount)
+ db.query(getSQLiteQuery(firstLoadPosition, firstLoadSize)).use { cursor ->
+ val rows = convertRows(cursor)
+ db.setTransactionSuccessful()
+ onResultCaller = { callback.onResult(rows, firstLoadPosition, totalCount) }
+ }
+ } else {
+ onResultCaller = { callback.onResult(emptyList(), 0, totalCount) }
}
} finally {
- if (cursor != null) {
- cursor.close();
- }
- mDb.endTransaction();
- if (sqLiteQuery != null) {
- sqLiteQuery.release();
- }
+ db.endTransaction()
}
-
- callback.onResult(list, firstLoadPosition, totalCount);
+ onResultCaller.invoke()
}
- @Override
- public void loadRange(@NonNull LoadRangeParams params,
- @NonNull LoadRangeCallback<T> callback) {
- callback.onResult(loadRange(params.startPosition, params.loadSize));
+ override fun loadRange(
+ params: LoadRangeParams,
+ callback: LoadRangeCallback<T>
+ ) {
+ callback.onResult(loadRange(params.startPosition, params.loadSize))
}
/**
@@ -196,44 +167,39 @@
*
* @hide
*/
- @SuppressWarnings("deprecation")
- @NonNull
- public List<T> loadRange(int startPosition, int loadCount) {
- final RoomSQLiteQuery sqLiteQuery = getSQLiteQuery(startPosition, loadCount);
- if (mInTransaction) {
- mDb.beginTransaction();
- Cursor cursor = null;
- //noinspection TryFinallyCanBeTryWithResources
- try {
- cursor = mDb.query(sqLiteQuery);
- List<T> rows = convertRows(cursor);
- mDb.setTransactionSuccessful();
- return rows;
- } finally {
- if (cursor != null) {
- cursor.close();
+ @Suppress("deprecation")
+ fun loadRange(startPosition: Int, loadCount: Int): List<T> {
+ val sqLiteQuery = getSQLiteQuery(startPosition, loadCount)
+ try {
+ if (inTransaction) {
+ db.beginTransaction()
+ try {
+ db.query(sqLiteQuery).use { cursor ->
+ val rows = convertRows(cursor)
+ db.setTransactionSuccessful()
+ return rows
+ }
+ } finally {
+ db.endTransaction()
}
- mDb.endTransaction();
- sqLiteQuery.release();
+ } else {
+ db.query(sqLiteQuery).use { cursor ->
+ return convertRows(cursor)
+ }
}
- } else {
- Cursor cursor = mDb.query(sqLiteQuery);
- //noinspection TryFinallyCanBeTryWithResources
- try {
- return convertRows(cursor);
- } finally {
- cursor.close();
- sqLiteQuery.release();
- }
+ } finally {
+ sqLiteQuery.release()
}
}
- private RoomSQLiteQuery getSQLiteQuery(int startPosition, int loadCount) {
- final RoomSQLiteQuery sqLiteQuery = RoomSQLiteQuery.acquire(mLimitOffsetQuery,
- mSourceQuery.getArgCount() + 2);
- sqLiteQuery.copyArgumentsFrom(mSourceQuery);
- sqLiteQuery.bindLong(sqLiteQuery.getArgCount() - 1, loadCount);
- sqLiteQuery.bindLong(sqLiteQuery.getArgCount(), startPosition);
- return sqLiteQuery;
+ private fun getSQLiteQuery(startPosition: Int, loadCount: Int): RoomSQLiteQuery {
+ val sqLiteQuery = RoomSQLiteQuery.acquire(
+ limitOffsetQuery,
+ sourceQuery.argCount + 2
+ )
+ sqLiteQuery.copyArgumentsFrom(sourceQuery)
+ sqLiteQuery.bindLong(sqLiteQuery.argCount - 1, loadCount.toLong())
+ sqLiteQuery.bindLong(sqLiteQuery.argCount, startPosition.toLong())
+ return sqLiteQuery
}
-}
+}
\ No newline at end of file