Merge "[FPS Range Settings] Improve the power and latency by setting the fps range before creating capture session" into androidx-main
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
index 93530a91..5778397 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextHelper.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
+import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
@@ -40,8 +41,11 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
+import androidx.annotation.UiThread;
import androidx.appcompat.R;
+import androidx.collection.LruCache;
import androidx.core.content.res.ResourcesCompat;
+import androidx.core.util.Pair;
import androidx.core.util.TypedValueCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.inputmethod.EditorInfoCompat;
@@ -86,6 +90,14 @@
mAutoSizeTextHelper = new AppCompatTextViewAutoSizeHelper(mView);
}
+ @RequiresApi(26)
+ @UiThread
+ @NonNull
+ static Typeface createVariationInstance(@NonNull Typeface baseTypeface,
+ @NonNull String fontVariationSettings) {
+ return Api26Impl.createVariationInstance(baseTypeface, fontVariationSettings);
+ }
+
@SuppressLint("NewApi")
void loadFromAttributes(@Nullable AttributeSet attrs, int defStyleAttr) {
final Context context = mView.getContext();
@@ -772,6 +784,17 @@
@RequiresApi(26)
static class Api26Impl {
+ /**
+ * Cache for variation instances created based on an existing Typeface
+ */
+ private static final LruCache<Pair<Typeface, String>, Typeface> sVariationsCache =
+ new LruCache<>(30);
+
+ /**
+ * Used to create variation instances; initialized lazily
+ */
+ private static @Nullable Paint sPaint;
+
private Api26Impl() {
// This class is not instantiable.
}
@@ -788,6 +811,54 @@
return textView.setFontVariationSettings(fontVariationSettings);
}
+ /**
+ * Create a new Typeface based on {@code baseTypeFace} with the specified variation
+ * settings. Uses a cache to avoid memory scaling with the number of AppCompatTextViews.
+ *
+ * @param baseTypeface the original typeface, preferably without variations applied
+ * (used both to create the new instance, and as a cache key).
+ * Note: this method will correctly handle instances with variations
+ * applied, as we have no way of detecting that. However, cache hit
+ * rates may be decreased.
+ * @param fontVariationSettings the new font variation settings.
+ * This is used as a cache key without sorting, to avoid
+ * additional per-TextView allocations to parse and sort the
+ * variation settings. App developers should strive to provide
+ * the settings in the same order every time within their app,
+ * in order to get the best cache performance.
+ * @return the new instance, or {@code null} if
+ * {@link Paint#setFontVariationSettings(String)} would return null for this
+ * Typeface and font variation settings string.
+ */
+ @Nullable
+ @UiThread
+ static Typeface createVariationInstance(@Nullable Typeface baseTypeface,
+ @Nullable String fontVariationSettings) {
+ Pair<Typeface, String> cacheKey = new Pair<>(baseTypeface, fontVariationSettings);
+
+ Typeface result = sVariationsCache.get(cacheKey);
+ if (result != null) {
+ return result;
+ }
+ Paint paint = sPaint != null ? sPaint : (sPaint = new Paint());
+
+ // Work around b/353609778
+ if (Objects.equals(paint.getFontVariationSettings(), fontVariationSettings)) {
+ paint.setFontVariationSettings(null);
+ }
+
+ // Use Paint to create a new Typeface based on an existing one
+ paint.setTypeface(baseTypeface);
+ boolean effective = paint.setFontVariationSettings(fontVariationSettings);
+ if (effective) {
+ result = paint.getTypeface();
+ sVariationsCache.put(cacheKey, result);
+ return result;
+ } else {
+ return null;
+ }
+ }
+
static int getAutoSizeStepGranularity(TextView textView) {
return textView.getAutoSizeStepGranularity();
}
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
index 0b7c10b..42f25b5 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
@@ -96,6 +96,20 @@
private boolean mIsSetTypefaceProcessing = false;
+ /**
+ * Equivalent to Typeface.mOriginalTypeface.
+ * Used to correctly emulate the behavior of getTypeface(), because we need to call setTypeface
+ * directly in order to implement caching of variation instances of typefaces.
+ */
+ private Typeface mOriginalTypeface;
+
+ /**
+ * The currently applied font variation settings.
+ * Used to make getFontVariationSettings somewhat more accurate with Typeface instance caching,
+ * as we don't call super.setFontVariationSettings.
+ */
+ private String mFontVariationSettings;
+
@Nullable
private SuperCaller mSuperCaller = null;
@@ -160,7 +174,6 @@
/**
* This should be accessed via
* {@link androidx.core.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
- *
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
@Override
@@ -173,7 +186,6 @@
/**
* This should be accessed via
* {@link androidx.core.view.ViewCompat#getBackgroundTintList(android.view.View)}
- *
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
@Override
@@ -186,7 +198,6 @@
/**
* This should be accessed via
* {@link androidx.core.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
- *
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
@Override
@@ -199,7 +210,6 @@
/**
* This should be accessed via
* {@link androidx.core.view.ViewCompat#getBackgroundTintMode(android.view.View)}
- *
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
@Override
@@ -217,6 +227,38 @@
}
}
+ /**
+ * Set font variation settings.
+ * See {@link TextView#setFontVariationSettings(String)} for details.
+ * <p>
+ * <em>Note:</em> Due to performance optimizations,
+ * {@code getPaint().getFontVariationSettings()} will be less reliable than if not using
+ * AppCompatTextView. You should prefer {@link #getFontVariationSettings()}, which will be more
+ * accurate. However, neither approach will work correctly if using Typeface objects with
+ * embedded font variation settings.
+ */
+ @RequiresApi(26)
+ @Override
+ public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
+ Typeface variationTypefaceInstance = AppCompatTextHelper.Api26Impl.createVariationInstance(
+ mOriginalTypeface, fontVariationSettings);
+ if (variationTypefaceInstance != null) {
+ // Call superclass method directly to bypass overwriting mOriginalTypeface
+ super.setTypeface(variationTypefaceInstance);
+ mFontVariationSettings = fontVariationSettings;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Nullable
+ @RequiresApi(26)
+ @Override
+ public String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
@Override
public void setFilters(@SuppressWarnings("ArrayReturn") @NonNull InputFilter[] filters) {
super.setFilters(getEmojiTextViewHelper().getFilters(filters));
@@ -755,6 +797,20 @@
}
@Override
+ public void setTypeface(@Nullable Typeface tf) {
+ mOriginalTypeface = tf;
+ super.setTypeface(tf);
+ }
+
+ @Override
+ @Nullable
+ // Code inspection reveals that the superclass method can return null.
+ @SuppressWarnings("InvalidNullabilityOverride")
+ public Typeface getTypeface() {
+ return mOriginalTypeface;
+ }
+
+ @Override
public void setTypeface(@Nullable Typeface tf, int style) {
if (mIsSetTypefaceProcessing) {
// b/151782655
diff --git a/buildSrc/jetpad-integration/src/main/java/androidx/build/jetpad/LibraryBuildInfoFile.java b/buildSrc/jetpad-integration/src/main/java/androidx/build/jetpad/LibraryBuildInfoFile.java
index bf7a859..9781b2e 100644
--- a/buildSrc/jetpad-integration/src/main/java/androidx/build/jetpad/LibraryBuildInfoFile.java
+++ b/buildSrc/jetpad-integration/src/main/java/androidx/build/jetpad/LibraryBuildInfoFile.java
@@ -45,7 +45,6 @@
public String kotlinVersion;
public String path;
public String sha;
- public String groupZipPath;
public String projectZipPath;
public Boolean groupIdRequiresSameVersion;
public ArrayList<Dependency> dependencies;
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
index 5a347ab..791d72d 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/Release.kt
@@ -18,7 +18,6 @@
import androidx.build.uptodatedness.cacheEvenIfNoOutputs
import java.io.File
import java.io.FileNotFoundException
-import java.util.Locale
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
@@ -121,14 +120,11 @@
object Release {
@Suppress("MemberVisibilityCanBePrivate")
const val PROJECT_ARCHIVE_ZIP_TASK_NAME = "createProjectZip"
- const val DIFF_TASK_PREFIX = "createDiffArchive"
- const val FULL_ARCHIVE_TASK_NAME = "createArchive"
- const val ALL_ARCHIVES_TASK_NAME = "createAllArchives"
+ private const val FULL_ARCHIVE_TASK_NAME = "createArchive"
+ private const val ALL_ARCHIVES_TASK_NAME = "createAllArchives"
const val DEFAULT_PUBLISH_CONFIG = "release"
- const val GROUP_ZIPS_FOLDER = "per-group-zips"
const val PROJECT_ZIPS_FOLDER = "per-project-zips"
- const val GROUP_ZIP_PREFIX = "gmaven"
- const val GLOBAL_ZIP_PREFIX = "top-of-tree-m2repository"
+ private const val GLOBAL_ZIP_PREFIX = "top-of-tree-m2repository"
// lazily created config action params so that we don't keep re-creating them
private var configActionParams: GMavenZipTask.ConfigAction.Params? = null
@@ -158,12 +154,6 @@
)
return
}
-
- val mavenGroup =
- androidXExtension.mavenGroup?.group
- ?: throw IllegalArgumentException(
- "Cannot register a project to release if it does not have a mavenGroup set up"
- )
if (!androidXExtension.isVersionSet()) {
throw IllegalArgumentException(
"Cannot register a project to release if it does not have a mavenVersion set up"
@@ -172,12 +162,7 @@
val version = project.version
val projectZipTask = getProjectZipTask(project)
- val zipTasks =
- listOf(
- projectZipTask,
- getGroupReleaseZipTask(project, mavenGroup),
- getGlobalFullZipTask(project)
- )
+ val zipTasks = listOf(projectZipTask, getGlobalFullZipTask(project))
val artifacts = androidXExtension.publishedArtifacts
val publishTask = project.tasks.named("publish")
@@ -295,28 +280,6 @@
)
}
- /** Creates and returns the zip task that includes artifacts only in the given maven group. */
- private fun getGroupReleaseZipTask(
- project: Project,
- group: String
- ): TaskProvider<GMavenZipTask> {
- return project.rootProject.maybeRegister(
- name = "${DIFF_TASK_PREFIX}For${groupToTaskNameSuffix(group)}",
- onConfigure = { task: GMavenZipTask ->
- GMavenZipTask.ConfigAction(
- getParams(
- project = project,
- distDir = File(project.getDistributionDirectory(), GROUP_ZIPS_FOLDER),
- fileNamePrefix = GROUP_ZIP_PREFIX,
- group = group
- )
- )
- .execute(task)
- },
- onRegister = { taskProvider -> project.addToAnchorTask(taskProvider) }
- )
- }
-
private fun getProjectZipTask(project: Project): TaskProvider<GMavenZipTask> {
val taskProvider =
project.tasks.register(PROJECT_ARCHIVE_ZIP_TASK_NAME, GMavenZipTask::class.java) {
@@ -403,7 +366,7 @@
}
}
- fun verifyFiles() {
+ private fun verifyFiles() {
val missingFiles = mutableListOf<String>()
val emptyDirs = mutableListOf<String>()
filesToVerify.forEach { file ->
@@ -478,15 +441,6 @@
return declaredTargets.toList()
}
-/** Converts the maven group into a readable task name. */
-private fun groupToTaskNameSuffix(group: String): String {
- return group.split('.').joinToString("") {
- it.replaceFirstChar { char ->
- if (char.isLowerCase()) char.titlecase(Locale.getDefault()) else char.toString()
- }
- }
-}
-
private fun Project.projectZipPrefix(): String {
return "${project.group}-${project.name}"
}
@@ -509,17 +463,3 @@
getZipName(projectZipPrefix(), "") +
"-${project.version}.zip"
}
-
-fun Project.getGroupZipPath(): String {
- return Release.GROUP_ZIPS_FOLDER +
- "/" +
- getZipName(Release.GROUP_ZIP_PREFIX, project.group.toString()) +
- ".zip"
-}
-
-fun Project.getGlobalZipFile(): File {
- return File(
- project.getDistributionDirectory(),
- getZipName(Release.GLOBAL_ZIP_PREFIX, "") + ".zip"
- )
-}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
index efe9eee..07f4db2 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
@@ -21,7 +21,6 @@
import androidx.build.LibraryGroup
import androidx.build.docs.CheckTipOfTreeDocsTask.Companion.requiresDocs
import androidx.build.getBuildInfoDirectory
-import androidx.build.getGroupZipPath
import androidx.build.getProjectZipPath
import androidx.build.getSupportRootFolder
import androidx.build.gitclient.getHeadShaProvider
@@ -92,8 +91,6 @@
@get:Input abstract val groupIdRequiresSameVersion: Property<Boolean>
- @get:Input abstract val groupZipPath: Property<String>
-
@get:Input abstract val projectZipPath: Property<String>
@get:[Input Optional]
@@ -139,7 +136,6 @@
libraryBuildInfoFile.path = projectDir.get()
libraryBuildInfoFile.sha = commit.get()
libraryBuildInfoFile.groupIdRequiresSameVersion = groupIdRequiresSameVersion.get()
- libraryBuildInfoFile.groupZipPath = groupZipPath.get()
libraryBuildInfoFile.projectZipPath = projectZipPath.get()
libraryBuildInfoFile.kotlinVersion = kotlinVersion.orNull
libraryBuildInfoFile.checks = ArrayList()
@@ -196,7 +192,6 @@
)
task.commit.set(shaProvider)
task.groupIdRequiresSameVersion.set(mavenGroup?.requireSameVersion ?: false)
- task.groupZipPath.set(project.getGroupZipPath())
task.projectZipPath.set(project.getProjectZipPath())
// Note:
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
index 6129f59..03633e9 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/FocusMeteringControl.java
@@ -458,6 +458,8 @@
*/
@ExecutedBy("mExecutor")
void triggerAePrecapture(@Nullable Completer<Void> completer) {
+ Logger.d(TAG, "triggerAePrecapture");
+
if (!mIsActive) {
if (completer != null) {
completer.setException(
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/ScreenFlashView.java b/camera/camera-view/src/main/java/androidx/camera/view/ScreenFlashView.java
index a42bd1b..529e630 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/ScreenFlashView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/ScreenFlashView.java
@@ -19,6 +19,8 @@
import static androidx.camera.core.ImageCapture.FLASH_MODE_SCREEN;
import static androidx.camera.core.impl.utils.Threads.checkMainThread;
+import android.animation.Animator;
+import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
@@ -29,6 +31,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
import androidx.annotation.UiThread;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCapture.ScreenFlash;
@@ -58,8 +61,8 @@
* {@link PreviewView} does not encompass the full screen, users may want to use this view
* separately so that whole screen can be encompassed during screen flash operation.
*
+ * @see #getScreenFlash
* @see ImageCapture#FLASH_MODE_SCREEN
- * @see PreviewView#getScreenFlash
*/
public final class ScreenFlashView extends View {
private static final String TAG = "ScreenFlashView";
@@ -67,6 +70,9 @@
private Window mScreenFlashWindow;
private ImageCapture.ScreenFlash mScreenFlash;
+ /** The timeout in seconds for the visibility animation at {@link ScreenFlash#apply}. */
+ private static final long ANIMATION_DURATION_MILLIS = 1000;
+
@UiThread
public ScreenFlashView(@NonNull Context context) {
this(context, null);
@@ -80,7 +86,7 @@
@UiThread
public ScreenFlashView(@NonNull Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
+ this(context, attrs, defStyleAttr, 0);
}
@UiThread
@@ -134,7 +140,7 @@
return;
}
mCameraController.setScreenFlashUiInfo(new ScreenFlashUiInfo(
- ScreenFlashUiInfo.ProviderType.SCREEN_FLASH_VIEW, control));
+ ScreenFlashUiInfo.ProviderType.SCREEN_FLASH_VIEW, control));
}
/**
@@ -170,45 +176,122 @@
if (mScreenFlashWindow != window) {
mScreenFlash = window == null ? null : new ScreenFlash() {
private float mPreviousBrightness;
+ private ValueAnimator mAnimator;
@Override
public void apply(long expirationTimeMillis,
@NonNull ImageCapture.ScreenFlashListener screenFlashListener) {
Logger.d(TAG, "ScreenFlash#apply");
- setAlpha(1f);
+ mPreviousBrightness = getBrightness();
+ setBrightness(1.0f);
- // Maximize screen brightness
- WindowManager.LayoutParams layoutParam = mScreenFlashWindow.getAttributes();
- mPreviousBrightness = layoutParam.screenBrightness;
- layoutParam.screenBrightness = 1F;
- mScreenFlashWindow.setAttributes(layoutParam);
-
- screenFlashListener.onCompleted();
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ mAnimator = animateToFullOpacity(screenFlashListener::onCompleted);
}
@Override
public void clear() {
Logger.d(TAG, "ScreenFlash#clearScreenFlashUi");
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ mAnimator = null;
+ }
+
setAlpha(0f);
// Restore screen brightness
- WindowManager.LayoutParams layoutParam = mScreenFlashWindow.getAttributes();
- layoutParam.screenBrightness = mPreviousBrightness;
- mScreenFlashWindow.setAttributes(layoutParam);
+ setBrightness(mPreviousBrightness);
}
};
}
}
+ private ValueAnimator animateToFullOpacity(@Nullable Runnable onAnimationEnd) {
+ Logger.d(TAG, "animateToFullOpacity");
+
+ ValueAnimator animator = ValueAnimator.ofFloat(0F, 1F);
+
+ // TODO: b/355168952 - Allow users to overwrite the animation duration.
+ animator.setDuration(getVisibilityRampUpAnimationDurationMillis());
+
+ animator.addUpdateListener(animation -> {
+ Logger.d(TAG, "animateToFullOpacity: value = " + (float) animation.getAnimatedValue());
+ setAlpha((float) animation.getAnimatedValue());
+ });
+
+ animator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(@NonNull Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation) {
+ Logger.d(TAG, "ScreenFlash#apply: onAnimationEnd");
+ if (onAnimationEnd != null) {
+ onAnimationEnd.run();
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(@NonNull Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(@NonNull Animator animation) {
+
+ }
+ });
+
+ animator.start();
+
+ return animator;
+ }
+
+ private float getBrightness() {
+ if (mScreenFlashWindow == null) {
+ Logger.e(TAG, "setBrightness: mScreenFlashWindow is null!");
+ return Float.NaN;
+ }
+
+ WindowManager.LayoutParams layoutParam = mScreenFlashWindow.getAttributes();
+ return layoutParam.screenBrightness;
+ }
+
+ private void setBrightness(float value) {
+ if (mScreenFlashWindow == null) {
+ Logger.e(TAG, "setBrightness: mScreenFlashWindow is null!");
+ return;
+ }
+
+ if (Float.isNaN(value)) {
+ Logger.e(TAG, "setBrightness: value is NaN!");
+ return;
+ }
+
+ WindowManager.LayoutParams layoutParam = mScreenFlashWindow.getAttributes();
+ layoutParam.screenBrightness = value;
+ mScreenFlashWindow.setAttributes(layoutParam);
+ Logger.d(TAG, "Brightness set to " + layoutParam.screenBrightness);
+ }
+
/**
* Returns an {@link ScreenFlash} implementation based on the {@link Window} instance
* set via {@link #setScreenFlashWindow(Window)}.
*
* <p> When {@link ScreenFlash#apply(long, ImageCapture.ScreenFlashListener)} is invoked,
- * this view becomes fully visible and screen brightness is maximized using the provided
- * {@code Window}. The default color of the overlay view is {@link Color#WHITE}. To change
+ * this view becomes fully visible gradually with an animation and screen brightness is
+ * maximized using the provided {@code Window}. Since brightness change of the display happens
+ * asynchronously and may take some time to be completed, the animation to ramp up visibility
+ * may require a duration of sufficient delay (decided internally) before
+ * {@link ImageCapture.ScreenFlashListener#onCompleted()} is invoked.
+ *
+ * <p> The default color of the overlay view is {@link Color#WHITE}. To change
* the color, use {@link #setBackgroundColor(int)}.
*
* <p> When {@link ScreenFlash#clear()} is invoked, the view
@@ -219,11 +302,23 @@
* Window} is set or none set at all, a null value will be returned by this method.
*
* @return A simple {@link ScreenFlash} implementation, or null value if a non-null
- * {@code Window} instance hasn't been set.
+ * {@code Window} instance hasn't been set.
*/
@UiThread
@Nullable
public ScreenFlash getScreenFlash() {
return mScreenFlash;
}
+
+ /**
+ * Returns the duration of the visibility ramp-up animation.
+ *
+ * <p> This is currently used in {@link ScreenFlash#apply}.
+ *
+ * @see #getScreenFlash()
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public long getVisibilityRampUpAnimationDurationMillis() {
+ return ANIMATION_DURATION_MILLIS;
+ }
}
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/ScreenFlashViewTest.kt b/camera/camera-view/src/test/java/androidx/camera/view/ScreenFlashViewTest.kt
index 981552b..510c632 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/ScreenFlashViewTest.kt
+++ b/camera/camera-view/src/test/java/androidx/camera/view/ScreenFlashViewTest.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.os.Build
+import android.os.Looper.getMainLooper
import android.view.Window
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
@@ -26,12 +27,14 @@
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.TimeUnit
+import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
+import org.robolectric.Shadows.shadowOf
import org.robolectric.annotation.Config
import org.robolectric.annotation.internal.DoNotInstrument
import org.robolectric.shadows.ShadowWindow
@@ -98,13 +101,29 @@
}
@Test
- fun isFullyVisible_whenScreenFlashApplyInvoked() {
+ fun isNotVisibleImmediately_whenScreenFlashApplyInvoked() {
val screenFlash = getScreenFlashAfterSettingWindow(true)
screenFlash!!.apply(
System.currentTimeMillis() +
TimeUnit.SECONDS.toMillis(ImageCapture.SCREEN_FLASH_UI_APPLY_TIMEOUT_SECONDS),
noOpListener,
)
+ assertThat(screenFlashView.alpha).isEqualTo(0f)
+ }
+
+ @Test
+ fun isFullyVisibleAfterAnimationDuration_whenScreenFlashApplyInvoked() = runBlocking {
+ val screenFlash = getScreenFlashAfterSettingWindow(true)
+ screenFlash!!.apply(
+ System.currentTimeMillis() +
+ TimeUnit.SECONDS.toMillis(ImageCapture.SCREEN_FLASH_UI_APPLY_TIMEOUT_SECONDS),
+ noOpListener,
+ )
+ shadowOf(getMainLooper())
+ .idleFor(
+ screenFlashView.visibilityRampUpAnimationDurationMillis + 1,
+ TimeUnit.MILLISECONDS
+ )
assertThat(screenFlashView.alpha).isEqualTo(1f)
}
diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle
index 595aef5..8eac369 100644
--- a/compose/animation/animation-core/build.gradle
+++ b/compose/animation/animation-core/build.gradle
@@ -46,7 +46,7 @@
implementation(project(":compose:ui:ui-unit"))
implementation(project(":compose:ui:ui-graphics"))
implementation(project(":compose:ui:ui-util"))
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
implementation(libs.kotlinStdlib)
api(libs.kotlinCoroutinesCore)
}
diff --git a/compose/animation/animation-graphics/build.gradle b/compose/animation/animation-graphics/build.gradle
index 16f1350..399503d 100644
--- a/compose/animation/animation-graphics/build.gradle
+++ b/compose/animation/animation-graphics/build.gradle
@@ -49,7 +49,7 @@
api(project(":compose:ui:ui-geometry"))
implementation(project(":compose:ui:ui-util"))
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
}
}
androidMain.dependencies {
diff --git a/compose/animation/animation/build.gradle b/compose/animation/animation/build.gradle
index f968628..a2950c4 100644
--- a/compose/animation/animation/build.gradle
+++ b/compose/animation/animation/build.gradle
@@ -52,7 +52,7 @@
implementation(project(":compose:ui:ui-util"))
implementation(project(":compose:ui:ui-graphics"))
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
}
}
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index 0fefb0e..703c2f2 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -44,8 +44,8 @@
api(project(":compose:ui:ui"))
implementation(project(":compose:runtime:runtime"))
implementation(project(":compose:ui:ui-util"))
- implementation(project(":collection:collection"))
implementation(project(":compose:ui:ui-unit"))
+ implementation("androidx.collection:collection:1.4.2")
}
}
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 79430fc..3c64ee1 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -93,8 +93,10 @@
method public static androidx.compose.foundation.CombinedClickableNode CombinedClickableNode(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, String? onLongClickLabel, kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.IndicationNodeFactory? indicationNodeFactory, boolean enabled, String? onClickLabel, androidx.compose.ui.semantics.Role? role);
method public static androidx.compose.ui.Modifier clickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
method public static androidx.compose.ui.Modifier clickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
- method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
- method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, optional boolean hapticFeedbackEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method @Deprecated public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, optional boolean hapticFeedbackEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method @Deprecated public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ClipScrollableContainerKt {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 3254ecd..a3d6ffc 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -93,8 +93,10 @@
method public static androidx.compose.foundation.CombinedClickableNode CombinedClickableNode(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, String? onLongClickLabel, kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.IndicationNodeFactory? indicationNodeFactory, boolean enabled, String? onClickLabel, androidx.compose.ui.semantics.Role? role);
method public static androidx.compose.ui.Modifier clickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
method public static androidx.compose.ui.Modifier clickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
- method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
- method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, optional boolean hapticFeedbackEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method @Deprecated public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, optional boolean hapticFeedbackEnabled, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
+ method @Deprecated public static androidx.compose.ui.Modifier combinedClickable(androidx.compose.ui.Modifier, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, optional String? onLongClickLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onLongClick, optional kotlin.jvm.functions.Function0<kotlin.Unit>? onDoubleClick, kotlin.jvm.functions.Function0<kotlin.Unit> onClick);
}
public final class ClipScrollableContainerKt {
diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle
index 196e79c..ed11b00 100644
--- a/compose/foundation/foundation/build.gradle
+++ b/compose/foundation/foundation/build.gradle
@@ -41,7 +41,7 @@
commonMain {
dependencies {
implementation(libs.kotlinStdlib)
- api(project(":collection:collection"))
+ api("androidx.collection:collection:1.4.2")
api(project(":compose:animation:animation"))
api(project(":compose:runtime:runtime"))
api(project(":compose:ui:ui"))
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableParameterizedKeyInputTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableParameterizedKeyInputTest.kt
index d5f2f0c..65b960f 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableParameterizedKeyInputTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableParameterizedKeyInputTest.kt
@@ -23,6 +23,7 @@
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ReusableContent
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -32,10 +33,13 @@
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusTarget
+import androidx.compose.ui.hapticfeedback.HapticFeedback
+import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.InputMode.Companion.Keyboard
import androidx.compose.ui.input.InputModeManager
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalInputModeManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.ExperimentalTestApi
@@ -45,6 +49,7 @@
import androidx.compose.ui.test.performKeyInput
import androidx.compose.ui.test.pressKey
import androidx.compose.ui.unit.dp
+import androidx.test.filters.LargeTest
import androidx.test.filters.MediumTest
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
@@ -232,6 +237,57 @@
}
}
+ @OptIn(ExperimentalTestApi::class)
+ @Test
+ @LargeTest
+ fun longClickWithKey_doesNotTriggerHapticFeedback() {
+ var clickCounter = 0
+ var longClickCounter = 0
+ val focusRequester = FocusRequester()
+ lateinit var inputModeManager: InputModeManager
+ val performedHaptics = mutableListOf<HapticFeedbackType>()
+
+ val hapticFeedback: HapticFeedback =
+ object : HapticFeedback {
+ override fun performHapticFeedback(hapticFeedbackType: HapticFeedbackType) {
+ performedHaptics += hapticFeedbackType
+ }
+ }
+ rule.setContent {
+ inputModeManager = LocalInputModeManager.current
+ CompositionLocalProvider(LocalHapticFeedback provides hapticFeedback) {
+ BasicText(
+ "ClickableText",
+ modifier =
+ Modifier.testTag("myClickable")
+ .focusRequester(focusRequester)
+ .combinedClickable(
+ onLongClick = { ++longClickCounter },
+ onClick = { ++clickCounter },
+ hapticFeedbackEnabled = true
+ )
+ )
+ }
+ }
+ rule.runOnIdle {
+ inputModeManager.requestInputMode(Keyboard)
+ focusRequester.requestFocus()
+ }
+
+ rule.onNodeWithTag("myClickable").performKeyInput {
+ assertThat(inputModeManager.inputMode).isEqualTo(Keyboard)
+ // The press duration is 100ms longer than the minimum required for a long press.
+ val durationMillis: Long = viewConfiguration.longPressTimeoutMillis + 100
+ pressKey(key, durationMillis)
+ }
+
+ rule.runOnIdle {
+ assertThat(longClickCounter).isEqualTo(1)
+ assertThat(clickCounter).isEqualTo(0)
+ assertThat(performedHaptics).isEmpty()
+ }
+ }
+
@Test
@OptIn(ExperimentalTestApi::class)
fun longClickWithKey_notInvokedIfFocusIsLostWhilePressed() {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableTest.kt
index 44c3864..165c8c5 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/CombinedClickableTest.kt
@@ -50,6 +50,8 @@
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.hapticfeedback.HapticFeedback
+import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.InputMode
import androidx.compose.ui.input.InputMode.Companion.Keyboard
import androidx.compose.ui.input.InputMode.Companion.Touch
@@ -57,6 +59,7 @@
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.platform.InspectableValue
import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalInputModeManager
import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
import androidx.compose.ui.platform.testTag
@@ -318,6 +321,107 @@
}
@Test
+ @LargeTest
+ fun longClick_hapticFeedbackEnabled() {
+ var counter = 0
+ val onClick: () -> Unit = { ++counter }
+ val performedHaptics = mutableListOf<HapticFeedbackType>()
+
+ val hapticFeedback: HapticFeedback =
+ object : HapticFeedback {
+ override fun performHapticFeedback(hapticFeedbackType: HapticFeedbackType) {
+ performedHaptics += hapticFeedbackType
+ }
+ }
+
+ rule.setContent {
+ CompositionLocalProvider(LocalHapticFeedback provides hapticFeedback) {
+ Box {
+ BasicText(
+ "ClickableText",
+ modifier =
+ Modifier.testTag("myClickable").combinedClickable(
+ onLongClick = onClick,
+ hapticFeedbackEnabled = true
+ ) {}
+ )
+ }
+ }
+ }
+
+ rule.onNodeWithTag("myClickable").performTouchInput { down(center) }
+
+ // Advance a small amount of time
+ rule.mainClock.advanceTimeBy(100)
+
+ rule.onNodeWithTag("myClickable").performTouchInput { up() }
+
+ // Releasing the press before the long click timeout shouldn't trigger haptic feedback
+ rule.runOnIdle { assertThat(counter).isEqualTo(0) }
+ rule.runOnIdle { assertThat(performedHaptics).isEmpty() }
+
+ rule.onNodeWithTag("myClickable").performTouchInput { down(center) }
+
+ // Advance past the long press timeout
+ rule.mainClock.advanceTimeBy(1000)
+
+ // Long press haptic feedback should be invoked
+ rule.runOnIdle { assertThat(counter).isEqualTo(1) }
+ rule.runOnIdle {
+ assertThat(performedHaptics).containsExactly(HapticFeedbackType.LongPress)
+ }
+ }
+
+ @Test
+ @LargeTest
+ fun longClick_hapticFeedbackDisabled() {
+ var counter = 0
+ val onClick: () -> Unit = { ++counter }
+ val performedHaptics = mutableListOf<HapticFeedbackType>()
+
+ val hapticFeedback: HapticFeedback =
+ object : HapticFeedback {
+ override fun performHapticFeedback(hapticFeedbackType: HapticFeedbackType) {
+ performedHaptics += hapticFeedbackType
+ }
+ }
+
+ rule.setContent {
+ CompositionLocalProvider(LocalHapticFeedback provides hapticFeedback) {
+ Box {
+ BasicText(
+ "ClickableText",
+ modifier =
+ Modifier.testTag("myClickable").combinedClickable(
+ onLongClick = onClick,
+ hapticFeedbackEnabled = false
+ ) {}
+ )
+ }
+ }
+ }
+
+ rule.onNodeWithTag("myClickable").performTouchInput { down(center) }
+
+ // Advance a small amount of time
+ rule.mainClock.advanceTimeBy(100)
+
+ rule.onNodeWithTag("myClickable").performTouchInput { up() }
+
+ rule.runOnIdle { assertThat(counter).isEqualTo(0) }
+ rule.runOnIdle { assertThat(performedHaptics).isEmpty() }
+
+ rule.onNodeWithTag("myClickable").performTouchInput { down(center) }
+
+ // Advance past the long press timeout
+ rule.mainClock.advanceTimeBy(1000)
+
+ // Long press should be invoked, without any haptics
+ rule.runOnIdle { assertThat(counter).isEqualTo(1) }
+ rule.runOnIdle { assertThat(performedHaptics).isEmpty() }
+ }
+
+ @Test
@OptIn(ExperimentalTestApi::class)
fun longClickWithEnterKeyThenDPadCenter_triggersListenerTwice() {
var clickCounter = 0
@@ -1808,7 +1912,8 @@
"onClick",
"onDoubleClick",
"onLongClick",
- "onLongClickLabel"
+ "onLongClickLabel",
+ "hapticFeedbackEnabled"
)
}
}
@@ -1836,7 +1941,8 @@
"onLongClick",
"onLongClickLabel",
"indicationNodeFactory",
- "interactionSource"
+ "interactionSource",
+ "hapticFeedbackEnabled"
)
}
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
index 5a2dde7..ee11b6e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
@@ -29,6 +29,8 @@
import androidx.compose.ui.composed
import androidx.compose.ui.focus.Focusability
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.hapticfeedback.HapticFeedback
+import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.KeyInputModifierNode
import androidx.compose.ui.input.key.key
@@ -48,6 +50,7 @@
import androidx.compose.ui.node.invalidateSemantics
import androidx.compose.ui.node.traverseAncestors
import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.Role
@@ -228,6 +231,7 @@
* @param onLongClickLabel semantic / accessibility label for the [onLongClick] action
* @param onLongClick will be called when user long presses on the element
* @param onDoubleClick will be called when user double clicks on the element
+ * @param hapticFeedbackEnabled whether to use the default [HapticFeedback] behavior
* @param onClick will be called when user clicks on the element
*/
fun Modifier.combinedClickable(
@@ -237,6 +241,56 @@
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
+ hapticFeedbackEnabled: Boolean = true,
+ onClick: () -> Unit
+) =
+ composed(
+ inspectorInfo =
+ debugInspectorInfo {
+ name = "combinedClickable"
+ properties["enabled"] = enabled
+ properties["onClickLabel"] = onClickLabel
+ properties["role"] = role
+ properties["onClick"] = onClick
+ properties["onDoubleClick"] = onDoubleClick
+ properties["onLongClick"] = onLongClick
+ properties["onLongClickLabel"] = onLongClickLabel
+ properties["hapticFeedbackEnabled"] = hapticFeedbackEnabled
+ }
+ ) {
+ val localIndication = LocalIndication.current
+ val interactionSource =
+ if (localIndication is IndicationNodeFactory) {
+ // We can fast path here as it will be created inside clickable lazily
+ null
+ } else {
+ // We need an interaction source to pass between the indication modifier and
+ // clickable, so
+ // by creating here we avoid another composed down the line
+ remember { MutableInteractionSource() }
+ }
+ Modifier.combinedClickable(
+ enabled = enabled,
+ onClickLabel = onClickLabel,
+ onLongClickLabel = onLongClickLabel,
+ onLongClick = onLongClick,
+ onDoubleClick = onDoubleClick,
+ onClick = onClick,
+ role = role,
+ indication = localIndication,
+ interactionSource = interactionSource,
+ hapticFeedbackEnabled = hapticFeedbackEnabled
+ )
+ }
+
+@Deprecated(message = "Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
+fun Modifier.combinedClickable(
+ enabled: Boolean = true,
+ onClickLabel: String? = null,
+ role: Role? = null,
+ onLongClickLabel: String? = null,
+ onLongClick: (() -> Unit)? = null,
+ onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
) =
composed(
@@ -272,7 +326,8 @@
onClick = onClick,
role = role,
indication = localIndication,
- interactionSource = interactionSource
+ interactionSource = interactionSource,
+ hapticFeedbackEnabled = true
)
}
@@ -322,6 +377,7 @@
* @param onLongClickLabel semantic / accessibility label for the [onLongClick] action
* @param onLongClick will be called when user long presses on the element
* @param onDoubleClick will be called when user double clicks on the element
+ * @param hapticFeedbackEnabled whether to use the default [HapticFeedback] behavior
* @param onClick will be called when user clicks on the element
*/
fun Modifier.combinedClickable(
@@ -333,6 +389,37 @@
onLongClickLabel: String? = null,
onLongClick: (() -> Unit)? = null,
onDoubleClick: (() -> Unit)? = null,
+ hapticFeedbackEnabled: Boolean = true,
+ onClick: () -> Unit
+) =
+ clickableWithIndicationIfNeeded(
+ interactionSource = interactionSource,
+ indication = indication
+ ) { intSource, indicationNodeFactory ->
+ CombinedClickableElement(
+ interactionSource = intSource,
+ indicationNodeFactory = indicationNodeFactory,
+ enabled = enabled,
+ onClickLabel = onClickLabel,
+ role = role,
+ onClick = onClick,
+ onLongClickLabel = onLongClickLabel,
+ onLongClick = onLongClick,
+ onDoubleClick = onDoubleClick,
+ hapticFeedbackEnabled = hapticFeedbackEnabled
+ )
+ }
+
+@Deprecated(message = "Maintained for binary compatibility", level = DeprecationLevel.HIDDEN)
+fun Modifier.combinedClickable(
+ interactionSource: MutableInteractionSource?,
+ indication: Indication?,
+ enabled: Boolean = true,
+ onClickLabel: String? = null,
+ role: Role? = null,
+ onLongClickLabel: String? = null,
+ onLongClick: (() -> Unit)? = null,
+ onDoubleClick: (() -> Unit)? = null,
onClick: () -> Unit
) =
clickableWithIndicationIfNeeded(
@@ -348,7 +435,8 @@
onClick = onClick,
onLongClickLabel = onLongClickLabel,
onLongClick = onLongClick,
- onDoubleClick = onDoubleClick
+ onDoubleClick = onDoubleClick,
+ hapticFeedbackEnabled = true
)
}
@@ -481,7 +569,8 @@
private val onClick: () -> Unit,
private val onLongClickLabel: String?,
private val onLongClick: (() -> Unit)?,
- private val onDoubleClick: (() -> Unit)?
+ private val onDoubleClick: (() -> Unit)?,
+ private val hapticFeedbackEnabled: Boolean,
) : ModifierNodeElement<CombinedClickableNodeImpl>() {
override fun create() =
CombinedClickableNodeImpl(
@@ -489,6 +578,7 @@
onLongClickLabel,
onLongClick,
onDoubleClick,
+ hapticFeedbackEnabled,
interactionSource,
indicationNodeFactory,
enabled,
@@ -497,6 +587,7 @@
)
override fun update(node: CombinedClickableNodeImpl) {
+ node.hapticFeedbackEnabled = hapticFeedbackEnabled
node.update(
onClick,
onLongClickLabel,
@@ -521,6 +612,7 @@
properties["onDoubleClick"] = onDoubleClick
properties["onLongClick"] = onLongClick
properties["onLongClickLabel"] = onLongClickLabel
+ properties["hapticFeedbackEnabled"] = hapticFeedbackEnabled
}
override fun equals(other: Any?): Boolean {
@@ -539,6 +631,7 @@
if (onLongClickLabel != other.onLongClickLabel) return false
if (onLongClick !== other.onLongClick) return false
if (onDoubleClick !== other.onDoubleClick) return false
+ if (hapticFeedbackEnabled != other.hapticFeedbackEnabled) return false
return true
}
@@ -553,6 +646,7 @@
result = 31 * result + (onLongClickLabel?.hashCode() ?: 0)
result = 31 * result + (onLongClick?.hashCode() ?: 0)
result = 31 * result + (onDoubleClick?.hashCode() ?: 0)
+ result = 31 * result + hapticFeedbackEnabled.hashCode()
return result
}
}
@@ -645,6 +739,7 @@
onLongClickLabel,
onLongClick,
onDoubleClick,
+ hapticFeedbackEnabled = true,
interactionSource,
indicationNodeFactory,
enabled,
@@ -696,6 +791,7 @@
private var onLongClickLabel: String?,
private var onLongClick: (() -> Unit)?,
private var onDoubleClick: (() -> Unit)?,
+ var hapticFeedbackEnabled: Boolean,
interactionSource: MutableInteractionSource?,
indicationNodeFactory: IndicationNodeFactory?,
enabled: Boolean,
@@ -722,7 +818,13 @@
} else null,
onLongPress =
if (enabled && onLongClick != null) {
- { onLongClick?.invoke() }
+ {
+ onLongClick?.invoke()
+ if (hapticFeedbackEnabled) {
+ currentValueOf(LocalHapticFeedback)
+ .performHapticFeedback(HapticFeedbackType.LongPress)
+ }
+ }
} else null,
onPress = { offset ->
if (enabled) {
diff --git a/compose/material/material-ripple/build.gradle b/compose/material/material-ripple/build.gradle
index 417619c..51fe754 100644
--- a/compose/material/material-ripple/build.gradle
+++ b/compose/material/material-ripple/build.gradle
@@ -44,7 +44,7 @@
api(project(":compose:foundation:foundation"))
api(project(":compose:runtime:runtime"))
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
implementation(project(":compose:animation:animation"))
implementation(project(":compose:ui:ui-util"))
}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt
index 86a552e..f971352 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt
@@ -21,16 +21,20 @@
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalExpandedNavigationRail
+import androidx.compose.material3.ModalExpandedNavigationRailState
import androidx.compose.material3.NavigationRail
import androidx.compose.material3.NavigationRailItem
import androidx.compose.material3.WideNavigationRail
import androidx.compose.material3.WideNavigationRailItem
+import androidx.compose.material3.rememberModalExpandedNavigationRailState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableIntState
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.testutils.LayeredComposeTestCase
import androidx.compose.testutils.ToggleableTestCase
import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
@@ -40,6 +44,8 @@
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,6 +58,7 @@
private val testCaseFactory = { NavigationRailTestCase() }
private val collapsedWideRailTestCaseFactory = { NavigationRailTestCase(true) }
private val expandedWideRailTestCaseFactory = { NavigationRailTestCase(true, true) }
+ private val modalExpandedRailTestCaseFactory = { ModalExpandedRailTestCase() }
@Test
fun firstPixel() {
@@ -113,6 +120,19 @@
assertOneRecomposition = false,
)
}
+
+ @Test
+ fun modalExpandedNavigationRail_firstPixel() {
+ benchmarkRule.benchmarkToFirstPixel(modalExpandedRailTestCaseFactory)
+ }
+
+ @Test
+ fun modalExpandedNavigationRail_stateChange() {
+ benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+ modalExpandedRailTestCaseFactory,
+ assertOneRecomposition = false,
+ )
+ }
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@@ -181,3 +201,48 @@
}
}
}
+
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
+internal class ModalExpandedRailTestCase() : LayeredComposeTestCase(), ToggleableTestCase {
+ private lateinit var state: ModalExpandedNavigationRailState
+ private lateinit var scope: CoroutineScope
+
+ @Composable
+ override fun MeasuredContent() {
+ state = rememberModalExpandedNavigationRailState()
+ scope = rememberCoroutineScope()
+
+ ModalExpandedNavigationRail(
+ onDismissRequest = {},
+ railState = state,
+ ) {
+ WideNavigationRailItem(
+ selected = true,
+ onClick = {},
+ icon = { Spacer(Modifier.size(24.dp)) },
+ railExpanded = true,
+ label = { Spacer(Modifier.size(24.dp)) }
+ )
+ WideNavigationRailItem(
+ selected = false,
+ onClick = {},
+ icon = { Spacer(Modifier.size(24.dp)) },
+ railExpanded = true,
+ label = { Spacer(Modifier.size(24.dp)) }
+ )
+ }
+ }
+
+ @Composable
+ override fun ContentWrappers(content: @Composable () -> Unit) {
+ MaterialExpressiveTheme { content() }
+ }
+
+ override fun toggleState() {
+ if (state.isOpen) {
+ scope.launch { state.close() }
+ } else {
+ scope.launch { state.open() }
+ }
+ }
+}
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 07af007..0544251c 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -244,21 +244,15 @@
}
public final class ButtonShapes {
- ctor public ButtonShapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoveredShape, androidx.compose.ui.graphics.Shape focusedShape, androidx.compose.ui.graphics.Shape checkedShape);
+ ctor public ButtonShapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method public androidx.compose.ui.graphics.Shape component1();
method public androidx.compose.ui.graphics.Shape component2();
method public androidx.compose.ui.graphics.Shape component3();
- method public androidx.compose.ui.graphics.Shape component4();
- method public androidx.compose.ui.graphics.Shape component5();
- method public androidx.compose.material3.ButtonShapes copy(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoveredShape, androidx.compose.ui.graphics.Shape focusedShape, androidx.compose.ui.graphics.Shape checkedShape);
+ method public androidx.compose.material3.ButtonShapes copy(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method public androidx.compose.ui.graphics.Shape getCheckedShape();
- method public androidx.compose.ui.graphics.Shape getFocusedShape();
- method public androidx.compose.ui.graphics.Shape getHoveredShape();
method public androidx.compose.ui.graphics.Shape getPressedShape();
method public androidx.compose.ui.graphics.Shape getShape();
property public final androidx.compose.ui.graphics.Shape checkedShape;
- property public final androidx.compose.ui.graphics.Shape focusedShape;
- property public final androidx.compose.ui.graphics.Shape hoveredShape;
property public final androidx.compose.ui.graphics.Shape pressedShape;
property public final androidx.compose.ui.graphics.Shape shape;
}
@@ -2552,18 +2546,12 @@
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getCheckedShape();
method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedCheckedShape();
- method public androidx.compose.ui.graphics.Shape getElevatedFocusedShape();
- method public androidx.compose.ui.graphics.Shape getElevatedHoveredShape();
method public androidx.compose.ui.graphics.Shape getElevatedPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
- method public androidx.compose.ui.graphics.Shape getFocusedShape();
- method public androidx.compose.ui.graphics.Shape getHoveredShape();
method public float getIconSize();
method public float getIconSpacing();
method public float getMinHeight();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedCheckedShape();
- method public androidx.compose.ui.graphics.Shape getOutlinedFocusedShape();
- method public androidx.compose.ui.graphics.Shape getOutlinedHoveredShape();
method public androidx.compose.ui.graphics.Shape getOutlinedPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
method public androidx.compose.ui.graphics.Shape getPressedShape();
@@ -2571,13 +2559,11 @@
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSquareShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTonalCheckedShape();
- method public androidx.compose.ui.graphics.Shape getTonalFocusedShape();
- method public androidx.compose.ui.graphics.Shape getTonalHoveredShape();
method public androidx.compose.ui.graphics.Shape getTonalPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTonalShape();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors outlinedToggleButtonColors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors outlinedToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
- method public androidx.compose.material3.ButtonShapes shapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoverShape, androidx.compose.ui.graphics.Shape focusShape, androidx.compose.ui.graphics.Shape checkedShape);
+ method public androidx.compose.material3.ButtonShapes shapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors toggleButtonColors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors toggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors tonalToggleButtonColors();
@@ -2588,15 +2574,9 @@
property public final float MinHeight;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape checkedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedCheckedShape;
- property public final androidx.compose.ui.graphics.Shape elevatedFocusedShape;
- property public final androidx.compose.ui.graphics.Shape elevatedHoveredShape;
property public final androidx.compose.ui.graphics.Shape elevatedPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
- property public final androidx.compose.ui.graphics.Shape focusedShape;
- property public final androidx.compose.ui.graphics.Shape hoveredShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedCheckedShape;
- property public final androidx.compose.ui.graphics.Shape outlinedFocusedShape;
- property public final androidx.compose.ui.graphics.Shape outlinedHoveredShape;
property public final androidx.compose.ui.graphics.Shape outlinedPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
property public final androidx.compose.ui.graphics.Shape pressedShape;
@@ -2604,8 +2584,6 @@
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape squareShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape tonalCheckedShape;
- property public final androidx.compose.ui.graphics.Shape tonalFocusedShape;
- property public final androidx.compose.ui.graphics.Shape tonalHoveredShape;
property public final androidx.compose.ui.graphics.Shape tonalPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape tonalShape;
field public static final androidx.compose.material3.ToggleButtonDefaults INSTANCE;
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 07af007..0544251c 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -244,21 +244,15 @@
}
public final class ButtonShapes {
- ctor public ButtonShapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoveredShape, androidx.compose.ui.graphics.Shape focusedShape, androidx.compose.ui.graphics.Shape checkedShape);
+ ctor public ButtonShapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method public androidx.compose.ui.graphics.Shape component1();
method public androidx.compose.ui.graphics.Shape component2();
method public androidx.compose.ui.graphics.Shape component3();
- method public androidx.compose.ui.graphics.Shape component4();
- method public androidx.compose.ui.graphics.Shape component5();
- method public androidx.compose.material3.ButtonShapes copy(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoveredShape, androidx.compose.ui.graphics.Shape focusedShape, androidx.compose.ui.graphics.Shape checkedShape);
+ method public androidx.compose.material3.ButtonShapes copy(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method public androidx.compose.ui.graphics.Shape getCheckedShape();
- method public androidx.compose.ui.graphics.Shape getFocusedShape();
- method public androidx.compose.ui.graphics.Shape getHoveredShape();
method public androidx.compose.ui.graphics.Shape getPressedShape();
method public androidx.compose.ui.graphics.Shape getShape();
property public final androidx.compose.ui.graphics.Shape checkedShape;
- property public final androidx.compose.ui.graphics.Shape focusedShape;
- property public final androidx.compose.ui.graphics.Shape hoveredShape;
property public final androidx.compose.ui.graphics.Shape pressedShape;
property public final androidx.compose.ui.graphics.Shape shape;
}
@@ -2552,18 +2546,12 @@
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getCheckedShape();
method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedCheckedShape();
- method public androidx.compose.ui.graphics.Shape getElevatedFocusedShape();
- method public androidx.compose.ui.graphics.Shape getElevatedHoveredShape();
method public androidx.compose.ui.graphics.Shape getElevatedPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getElevatedShape();
- method public androidx.compose.ui.graphics.Shape getFocusedShape();
- method public androidx.compose.ui.graphics.Shape getHoveredShape();
method public float getIconSize();
method public float getIconSpacing();
method public float getMinHeight();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedCheckedShape();
- method public androidx.compose.ui.graphics.Shape getOutlinedFocusedShape();
- method public androidx.compose.ui.graphics.Shape getOutlinedHoveredShape();
method public androidx.compose.ui.graphics.Shape getOutlinedPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getOutlinedShape();
method public androidx.compose.ui.graphics.Shape getPressedShape();
@@ -2571,13 +2559,11 @@
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getSquareShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTonalCheckedShape();
- method public androidx.compose.ui.graphics.Shape getTonalFocusedShape();
- method public androidx.compose.ui.graphics.Shape getTonalHoveredShape();
method public androidx.compose.ui.graphics.Shape getTonalPressedShape();
method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getTonalShape();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors outlinedToggleButtonColors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors outlinedToggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
- method public androidx.compose.material3.ButtonShapes shapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape hoverShape, androidx.compose.ui.graphics.Shape focusShape, androidx.compose.ui.graphics.Shape checkedShape);
+ method public androidx.compose.material3.ButtonShapes shapes(androidx.compose.ui.graphics.Shape shape, androidx.compose.ui.graphics.Shape pressedShape, androidx.compose.ui.graphics.Shape checkedShape);
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors toggleButtonColors();
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors toggleButtonColors(optional long containerColor, optional long contentColor, optional long disabledContainerColor, optional long disabledContentColor, optional long checkedContainerColor, optional long checkedContentColor);
method @androidx.compose.runtime.Composable public androidx.compose.material3.ToggleButtonColors tonalToggleButtonColors();
@@ -2588,15 +2574,9 @@
property public final float MinHeight;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape checkedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedCheckedShape;
- property public final androidx.compose.ui.graphics.Shape elevatedFocusedShape;
- property public final androidx.compose.ui.graphics.Shape elevatedHoveredShape;
property public final androidx.compose.ui.graphics.Shape elevatedPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape elevatedShape;
- property public final androidx.compose.ui.graphics.Shape focusedShape;
- property public final androidx.compose.ui.graphics.Shape hoveredShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedCheckedShape;
- property public final androidx.compose.ui.graphics.Shape outlinedFocusedShape;
- property public final androidx.compose.ui.graphics.Shape outlinedHoveredShape;
property public final androidx.compose.ui.graphics.Shape outlinedPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape outlinedShape;
property public final androidx.compose.ui.graphics.Shape pressedShape;
@@ -2604,8 +2584,6 @@
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape shape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape squareShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape tonalCheckedShape;
- property public final androidx.compose.ui.graphics.Shape tonalFocusedShape;
- property public final androidx.compose.ui.graphics.Shape tonalHoveredShape;
property public final androidx.compose.ui.graphics.Shape tonalPressedShape;
property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape tonalShape;
field public static final androidx.compose.material3.ToggleButtonDefaults INSTANCE;
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ToggleButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ToggleButtonSamples.kt
index 8460484..b215df5 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ToggleButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ToggleButtonSamples.kt
@@ -57,8 +57,6 @@
ButtonShapes(
shape = ToggleButtonDefaults.roundShape,
pressedShape = ToggleButtonDefaults.pressedShape,
- hoveredShape = ToggleButtonDefaults.hoveredShape,
- focusedShape = ToggleButtonDefaults.focusedShape,
checkedShape = ToggleButtonDefaults.squareShape
)
ToggleButton(checked = checked, onCheckedChange = { checked = it }, shapes = shapes) {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ToggleButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ToggleButton.kt
index ed0c3b7..8ce3633 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ToggleButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ToggleButton.kt
@@ -21,11 +21,9 @@
import androidx.compose.animation.core.SpringSpec
import androidx.compose.animation.core.spring
import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.interaction.FocusInteraction
-import androidx.compose.foundation.interaction.HoverInteraction
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.interaction.PressInteraction
+import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
@@ -45,7 +43,6 @@
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@@ -63,15 +60,14 @@
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
/**
* TODO link to mio page when available.
*
* Toggle button is a toggleable button that switches between primary and tonal colors depending on
- * [checked]'s value. It also morphs between the five shapes provided in [shapes] depending on the
- * state of the interaction with the toggle button as long as the five shapes provided our
+ * [checked]'s value. It also morphs between the three shapes provided in [shapes] depending on the
+ * state of the interaction with the toggle button as long as the three shapes provided our
* [CornerBasedShape]s. If a shape in [shapes] isn't a [CornerBasedShape], then toggle button will
* toggle between the [ButtonShapes] according to user interaction.
*
@@ -120,8 +116,6 @@
ToggleButtonDefaults.shapes(
ToggleButtonDefaults.shape,
ToggleButtonDefaults.pressedShape,
- ToggleButtonDefaults.hoveredShape,
- ToggleButtonDefaults.focusedShape,
ToggleButtonDefaults.checkedShape
),
colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
@@ -136,66 +130,31 @@
val isCornerBasedShape =
shapes.shape is CornerBasedShape &&
shapes.checkedShape is CornerBasedShape &&
- shapes.pressedShape is CornerBasedShape &&
- shapes.hoveredShape is CornerBasedShape &&
- shapes.focusedShape is CornerBasedShape
+ shapes.pressedShape is CornerBasedShape
- var pressed by remember { mutableStateOf(false) }
- var hovered by remember { mutableStateOf(false) }
- var focused by remember { mutableStateOf(false) }
+ val pressed by interactionSource.collectIsPressedAsState()
val state: AnimatedShapeState? =
if (isCornerBasedShape) {
val defaultShape = shapes.shape as CornerBasedShape
val pressedShape = shapes.pressedShape as CornerBasedShape
- val hoveredShape = shapes.hoveredShape as CornerBasedShape
- val focusedShape = shapes.focusedShape as CornerBasedShape
val checkedShape = shapes.checkedShape as CornerBasedShape
remember {
AnimatedShapeState(
startShape = if (checked) checkedShape else defaultShape,
defaultShape = defaultShape,
pressedShape = pressedShape,
- hoveredShape = hoveredShape,
- focusedShape = focusedShape,
checkedShape = checkedShape,
spring(),
)
}
} else null
- LaunchedEffect(interactionSource) {
- interactionSource.interactions.collectLatest { interaction ->
- when (interaction) {
- is PressInteraction.Press -> {
- pressed = true
- }
- is HoverInteraction.Enter -> {
- hovered = true
- }
- is FocusInteraction.Focus -> {
- focused = true
- }
- is PressInteraction.Release,
- is PressInteraction.Cancel -> {
- pressed = false
- }
- is HoverInteraction.Exit -> {
- hovered = false
- }
- is FocusInteraction.Unfocus -> {
- focused = false
- }
- }
- }
- }
-
val containerColor = colors.containerColor(enabled, checked)
val contentColor = colors.contentColor(enabled, checked)
val shadowElevation = elevation?.shadowElevation(enabled, interactionSource)?.value ?: 0.dp
- val buttonShape =
- shapeByInteraction(isCornerBasedShape, state, shapes, pressed, hovered, focused, checked)
+ val buttonShape = shapeByInteraction(isCornerBasedShape, state, shapes, pressed, checked)
Surface(
checked = checked,
@@ -234,8 +193,8 @@
* TODO link to mio page when available.
*
* Toggle button is a toggleable button that switches between primary and tonal colors depending on
- * [checked]'s value. It also morphs between the five shapes provided in [shapes] depending on the
- * state of the interaction with the toggle button as long as the five shapes provided our
+ * [checked]'s value. It also morphs between the three shapes provided in [shapes] depending on the
+ * state of the interaction with the toggle button as long as the three shapes provided our
* [CornerBasedShape]s. If a shape in [shapes] isn't a [CornerBasedShape], then toggle button will
* toggle between the [ButtonShapes] according to user interaction.
*
@@ -282,8 +241,6 @@
ToggleButtonDefaults.shapes(
ToggleButtonDefaults.elevatedShape,
ToggleButtonDefaults.elevatedPressedShape,
- ToggleButtonDefaults.elevatedHoveredShape,
- ToggleButtonDefaults.elevatedFocusedShape,
ToggleButtonDefaults.elevatedCheckedShape
),
colors: ToggleButtonColors = ToggleButtonDefaults.elevatedToggleButtonColors(),
@@ -311,8 +268,8 @@
* TODO link to mio page when available.
*
* Toggle button is a toggleable button that switches between primary and tonal colors depending on
- * [checked]'s value. It also morphs between the five shapes provided in [shapes] depending on the
- * state of the interaction with the toggle button as long as the five shapes provided our
+ * [checked]'s value. It also morphs between the three shapes provided in [shapes] depending on the
+ * state of the interaction with the toggle button as long as the three shapes provided our
* [CornerBasedShape]s. If a shape in [shapes] isn't a [CornerBasedShape], then toggle button will
* toggle between the [ButtonShapes] according to user interaction.
*
@@ -362,8 +319,6 @@
ToggleButtonDefaults.shapes(
ToggleButtonDefaults.tonalShape,
ToggleButtonDefaults.tonalPressedShape,
- ToggleButtonDefaults.tonalHoveredShape,
- ToggleButtonDefaults.tonalFocusedShape,
ToggleButtonDefaults.tonalCheckedShape
),
colors: ToggleButtonColors = ToggleButtonDefaults.tonalToggleButtonColors(),
@@ -391,8 +346,8 @@
* TODO link to mio page when available.
*
* Toggle button is a toggleable button that switches between primary and tonal colors depending on
- * [checked]'s value. It also morphs between the five shapes provided in [shapes] depending on the
- * state of the interaction with the toggle button as long as the five shapes provided our
+ * [checked]'s value. It also morphs between the three shapes provided in [shapes] depending on the
+ * state of the interaction with the toggle button as long as the three shapes provided our
* [CornerBasedShape]s. If a shape in [shapes] isn't a [CornerBasedShape], then toggle button will
* toggle between the [ButtonShapes] according to user interaction.
*
@@ -440,8 +395,6 @@
ToggleButtonDefaults.shapes(
ToggleButtonDefaults.outlinedShape,
ToggleButtonDefaults.outlinedPressedShape,
- ToggleButtonDefaults.outlinedHoveredShape,
- ToggleButtonDefaults.outlinedFocusedShape,
ToggleButtonDefaults.outlinedCheckedShape
),
colors: ToggleButtonColors = ToggleButtonDefaults.outlinedToggleButtonColors(),
@@ -506,17 +459,10 @@
*
* @param shape the unchecked shape for [ButtonShapes]
* @param pressedShape the unchecked shape for [ButtonShapes]
- * @param hoverShape the unchecked shape for [ButtonShapes]
- * @param focusShape the unchecked shape for [ButtonShapes]
* @param checkedShape the unchecked shape for [ButtonShapes]
*/
- fun shapes(
- shape: Shape,
- pressedShape: Shape,
- hoverShape: Shape,
- focusShape: Shape,
- checkedShape: Shape
- ): ButtonShapes = ButtonShapes(shape, pressedShape, hoverShape, focusShape, checkedShape)
+ fun shapes(shape: Shape, pressedShape: Shape, checkedShape: Shape): ButtonShapes =
+ ButtonShapes(shape, pressedShape, checkedShape)
/** A round shape that can be used for all [ToggleButton]s and its variants */
val roundShape: Shape
@@ -554,30 +500,6 @@
/** The default pressed shape for [OutlinedToggleButton] */
val outlinedPressedShape: Shape = RoundedCornerShape(6.dp)
- /** The default hovered shape for [ToggleButton] */
- val hoveredShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default hovered shape for [ElevatedToggleButton] */
- val elevatedHoveredShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default hovered shape for [TonalToggleButton] */
- val tonalHoveredShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default hovered shape for [OutlinedToggleButton] */
- val outlinedHoveredShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default focused shape for [ToggleButton] */
- val focusedShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default focused shape for [ElevatedToggleButton] */
- val elevatedFocusedShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default focused shape for [TonalToggleButton] */
- val tonalFocusedShape: Shape = RoundedCornerShape(6.dp)
-
- /** The default focused shape for [OutlinedToggleButton] */
- val outlinedFocusedShape: Shape = RoundedCornerShape(6.dp)
-
// TODO: Change this to the new ButtonSmallTokens.SelectedShape when available
/** The default checked shape for [ToggleButton] */
val checkedShape: Shape
@@ -939,17 +861,9 @@
*
* @property shape is the unchecked shape.
* @property pressedShape is the pressed shape.
- * @property hoveredShape is the hovered shape.
- * @property focusedShape is the focused shape.
* @property checkedShape is the checked shape.
*/
-data class ButtonShapes(
- val shape: Shape,
- val pressedShape: Shape,
- val hoveredShape: Shape,
- val focusedShape: Shape,
- val checkedShape: Shape
-)
+data class ButtonShapes(val shape: Shape, val pressedShape: Shape, val checkedShape: Shape)
@Composable
private fun shapeByInteraction(
@@ -957,19 +871,13 @@
state: AnimatedShapeState?,
shapes: ButtonShapes,
pressed: Boolean,
- hovered: Boolean,
- focused: Boolean,
checked: Boolean
): Shape {
return if (isCornerBasedShape) {
if (state != null) {
- LaunchedEffect(pressed, hovered, focused, checked) {
+ LaunchedEffect(pressed, checked) {
if (pressed) {
state.animateToPressed()
- } else if (hovered) {
- state.animateToHovered()
- } else if (focused) {
- state.animateToFocused()
} else if (checked) {
state.animateToChecked()
} else {
@@ -982,10 +890,6 @@
}
} else if (pressed) {
shapes.pressedShape
- } else if (hovered) {
- shapes.hoveredShape
- } else if (focused) {
- shapes.focusedShape
} else if (checked) {
shapes.checkedShape
} else {
@@ -997,6 +901,7 @@
private fun rememberAnimatedShape(state: AnimatedShapeState): Shape {
val density = LocalDensity.current
state.density = density
+
return remember(density) {
object : Shape {
@@ -1028,8 +933,6 @@
val startShape: CornerBasedShape,
val defaultShape: CornerBasedShape,
val pressedShape: CornerBasedShape,
- val hoveredShape: CornerBasedShape,
- val focusedShape: CornerBasedShape,
val checkedShape: CornerBasedShape,
val spec: SpringSpec<Float>,
) {
@@ -1063,10 +966,6 @@
suspend fun animateToDefault() = animateToShape(defaultShape)
- suspend fun animateToHovered() = animateToShape(hoveredShape)
-
- suspend fun animateToFocused() = animateToShape(focusedShape)
-
private suspend fun animateToShape(shape: CornerBasedShape) = coroutineScope {
launch { topStart?.animateTo(shape.topStart.toPx(size, density), spec) }
launch { topEnd?.animateTo(shape.topEnd.toPx(size, density), spec) }
diff --git a/compose/runtime/runtime/build.gradle b/compose/runtime/runtime/build.gradle
index a82f5ac..fc61115 100644
--- a/compose/runtime/runtime/build.gradle
+++ b/compose/runtime/runtime/build.gradle
@@ -43,7 +43,7 @@
dependencies {
implementation(libs.kotlinStdlibCommon)
implementation(libs.kotlinCoroutinesCore)
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
}
}
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
index 2f07d423..c58bad7 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
@@ -120,37 +120,6 @@
/** IME visibility is only reliable on API 23+, where we have access to the root WindowInsets */
@SdkSuppress(minSdkVersion = 23)
- @Test
- public fun do_not_show_IME_if_TextView_in_dialog_not_focused() {
- val dialog =
- scenario.withActivity {
- object : Dialog(this) {
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
- WindowCompat.setDecorFitsSystemWindows(window!!, false)
- }
- }
- .apply { setContentView(R.layout.insets_compat_activity) }
- }
-
- val editText = dialog.findViewById<TextView>(R.id.edittext)
-
- // We hide the edit text to ensure it won't be automatically focused
- scenario.onActivity {
- dialog.show()
- editText.visibility = View.GONE
- assertThat(editText.isFocused, `is`(false))
- }
-
- val type = WindowInsetsCompat.Type.ime()
- scenario.onActivity {
- WindowCompat.getInsetsController(dialog.window!!, editText).show(type)
- }
- container.assertInsetsVisibility(type, false)
- }
-
- /** IME visibility is only reliable on API 23+, where we have access to the root WindowInsets */
- @SdkSuppress(minSdkVersion = 23)
@Ignore("b/294556594")
@Test
fun show_IME_fromEditText_in_dialog() {
diff --git a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
index b165f5c..fcf65ad 100644
--- a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
@@ -78,7 +78,8 @@
}
/**
- * Cache for Typeface objects dynamically loaded from assets.
+ * Cache for Typeface objects dynamically loaded from assets,
+ * keyed by {@link #createResourceUid(Resources, int, String, int, int)}
*/
private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
diff --git a/core/core/src/main/java/androidx/core/provider/FontRequestWorker.java b/core/core/src/main/java/androidx/core/provider/FontRequestWorker.java
index 761c25b..509de8d 100644
--- a/core/core/src/main/java/androidx/core/provider/FontRequestWorker.java
+++ b/core/core/src/main/java/androidx/core/provider/FontRequestWorker.java
@@ -58,6 +58,9 @@
private FontRequestWorker() {}
+ /**
+ * Keyed by {@link #createCacheId(List, int)}
+ */
static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);
private static final ExecutorService DEFAULT_EXECUTOR_SERVICE = RequestExecutor
diff --git a/core/core/src/main/java/androidx/core/view/WindowCompat.java b/core/core/src/main/java/androidx/core/view/WindowCompat.java
index 679f4cf..3c16649 100644
--- a/core/core/src/main/java/androidx/core/view/WindowCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowCompat.java
@@ -164,9 +164,13 @@
static void setDecorFitsSystemWindows(@NonNull Window window,
final boolean decorFitsSystemWindows) {
+ final int stableFlag = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+
final View decorView = window.getDecorView();
final int sysUiVis = decorView.getSystemUiVisibility();
- decorView.setSystemUiVisibility(sysUiVis | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ decorView.setSystemUiVisibility(decorFitsSystemWindows
+ ? sysUiVis & ~stableFlag
+ : sysUiVis | stableFlag);
window.setDecorFitsSystemWindows(decorFitsSystemWindows);
}
}
diff --git a/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
index f7400fa..e74ec94 100644
--- a/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowInsetsControllerCompat.java
@@ -393,6 +393,8 @@
}
private static class Impl {
+ static final int KEY_BEHAVIOR = 356039078;
+
Impl() {
//private
}
@@ -412,7 +414,7 @@
}
int getSystemBarsBehavior() {
- return 0;
+ return BEHAVIOR_DEFAULT;
}
public boolean isAppearanceLightStatusBars() {
@@ -533,6 +535,7 @@
@Override
void setSystemBarsBehavior(int behavior) {
+ mWindow.getDecorView().setTag(KEY_BEHAVIOR, behavior);
switch (behavior) {
case BEHAVIOR_DEFAULT:
unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
@@ -551,7 +554,8 @@
@Override
int getSystemBarsBehavior() {
- return 0;
+ final Object behaviorTag = mWindow.getDecorView().getTag(KEY_BEHAVIOR);
+ return behaviorTag != null ? (int) behaviorTag : BEHAVIOR_DEFAULT;
}
@Override
@@ -777,7 +781,28 @@
*/
@Override
void setSystemBarsBehavior(@Behavior int behavior) {
- mInsetsController.setSystemBarsBehavior(behavior);
+ if (mWindow != null) {
+ // Use the legacy way to control the behavior as a workaround because API 30 has a
+ // bug that the behavior might be cleared unexpectedly after setting a LayoutParam
+ // to a window.
+ mWindow.getDecorView().setTag(KEY_BEHAVIOR, behavior);
+ switch (behavior) {
+ case BEHAVIOR_DEFAULT:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE);
+ break;
+ case BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE);
+ setSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ break;
+ case BEHAVIOR_SHOW_BARS_BY_TOUCH:
+ unsetSystemUiFlag(View.SYSTEM_UI_FLAG_IMMERSIVE
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ break;
+ }
+ } else {
+ mInsetsController.setSystemBarsBehavior(behavior);
+ }
}
/**
@@ -790,7 +815,12 @@
@Override
@Behavior
int getSystemBarsBehavior() {
- return mInsetsController.getSystemBarsBehavior();
+ if (mWindow != null) {
+ final Object behaviorTag = mWindow.getDecorView().getTag(KEY_BEHAVIOR);
+ return behaviorTag != null ? (int) behaviorTag : BEHAVIOR_DEFAULT;
+ } else {
+ return mInsetsController.getSystemBarsBehavior();
+ }
}
@Override
@@ -839,8 +869,48 @@
}
}
+ @RequiresApi(31)
+ private static class Impl31 extends Impl30 {
+
+ Impl31(@NonNull Window window,
+ @NonNull WindowInsetsControllerCompat compatController,
+ @NonNull SoftwareKeyboardControllerCompat softwareKeyboardControllerCompat) {
+ super(window, compatController, softwareKeyboardControllerCompat);
+ }
+
+ Impl31(@NonNull WindowInsetsController insetsController,
+ @NonNull WindowInsetsControllerCompat compatController,
+ @NonNull SoftwareKeyboardControllerCompat softwareKeyboardControllerCompat) {
+ super(insetsController, compatController, softwareKeyboardControllerCompat);
+ }
+
+ /**
+ * Controls the behavior of system bars.
+ *
+ * @param behavior Determines how the bars behave when being hidden by the application.
+ * @see #getSystemBarsBehavior
+ */
+ @Override
+ void setSystemBarsBehavior(@Behavior int behavior) {
+ mInsetsController.setSystemBarsBehavior(behavior);
+ }
+
+ /**
+ * Retrieves the requested behavior of system bars.
+ *
+ * @return the system bar behavior controlled by this window.
+ * @see #setSystemBarsBehavior(int)
+ */
+ @SuppressLint("WrongConstant")
+ @Override
+ @Behavior
+ int getSystemBarsBehavior() {
+ return mInsetsController.getSystemBarsBehavior();
+ }
+ }
+
@RequiresApi(35)
- private static class Impl35 extends Impl30 {
+ private static class Impl35 extends Impl31 {
Impl35(@NonNull Window window,
@NonNull WindowInsetsControllerCompat compatController,
diff --git a/datastore/datastore-core/build.gradle b/datastore/datastore-core/build.gradle
index 0a0a304..d7eaded0 100644
--- a/datastore/datastore-core/build.gradle
+++ b/datastore/datastore-core/build.gradle
@@ -80,7 +80,7 @@
dependencies {
api(libs.kotlinStdlib)
api(libs.kotlinCoroutinesCore)
- api(project(":annotation:annotation"))
+ api("androidx.annotation:annotation:1.8.1")
}
}
diff --git a/datastore/datastore/build.gradle b/datastore/datastore/build.gradle
index c59b19f..05776a1 100644
--- a/datastore/datastore/build.gradle
+++ b/datastore/datastore/build.gradle
@@ -47,7 +47,7 @@
dependencies {
api(libs.kotlinStdlib)
api(libs.kotlinCoroutinesCore)
- api(project(":annotation:annotation"))
+ api("androidx.annotation:annotation:1.8.1")
api(project(":datastore:datastore-core"))
api(project(":datastore:datastore-core-okio"))
}
diff --git a/hilt/hilt-compiler/build.gradle b/hilt/hilt-compiler/build.gradle
index 7980e5f..3213852 100644
--- a/hilt/hilt-compiler/build.gradle
+++ b/hilt/hilt-compiler/build.gradle
@@ -39,7 +39,7 @@
implementation(libs.kspApi)
testImplementation(project(":hilt:hilt-common"))
- testImplementation(project(":annotation:annotation"))
+ testImplementation("androidx.annotation:annotation:1.8.1")
testImplementation(libs.junit)
testImplementation(libs.truth)
testImplementation(project(":room:room-compiler-processing-testing"))
diff --git a/paging/integration-tests/testapp/build.gradle b/paging/integration-tests/testapp/build.gradle
index cbd8d34..a1918e9 100644
--- a/paging/integration-tests/testapp/build.gradle
+++ b/paging/integration-tests/testapp/build.gradle
@@ -41,12 +41,10 @@
// Only needed to ensure version of annotation:annotation matches in impl
// and androidTestImpl, for both AOSP and playground builds.
- implementation(project(":annotation:annotation"))
- implementation(project(":annotation:annotation-experimental"))
+ implementation("androidx.annotation:annotation:1.8.1")
+ implementation("androidx.annotation:annotation-experimental:1.4.1")
// Align dependencies in debugRuntimeClasspath and debugAndroidTestRuntimeClasspath.
- androidTestImplementation(project(":annotation:annotation"))
- androidTestImplementation(project(":annotation:annotation-experimental"))
androidTestImplementation(libs.kotlinTest)
androidTestImplementation(libs.testCore)
androidTestImplementation(libs.testExtJunit)
diff --git a/remotecallback/remotecallback/build.gradle b/remotecallback/remotecallback/build.gradle
index e5ff2a7..c1da69a 100644
--- a/remotecallback/remotecallback/build.gradle
+++ b/remotecallback/remotecallback/build.gradle
@@ -30,14 +30,14 @@
dependencies {
api("androidx.annotation:annotation:1.8.1")
- implementation(project(":collection:collection"))
+ implementation("androidx.collection:collection:1.4.2")
androidTestImplementation(libs.testExtJunit)
androidTestImplementation(libs.testCore)
androidTestImplementation(libs.testRunner)
androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
- androidTestAnnotationProcessor (project(":remotecallback:remotecallback-processor"))
+ androidTestAnnotationProcessor(project(":remotecallback:remotecallback-processor"))
}
android {
diff --git a/resourceinspection/resourceinspection-processor/build.gradle b/resourceinspection/resourceinspection-processor/build.gradle
index 720cf10e..5251358 100644
--- a/resourceinspection/resourceinspection-processor/build.gradle
+++ b/resourceinspection/resourceinspection-processor/build.gradle
@@ -46,7 +46,7 @@
testImplementation(libs.truth)
testRuntimeOnly(project(":resourceinspection:resourceinspection-annotation"))
- testRuntimeOnly(project(":annotation:annotation"))
+ testRuntimeOnly("androidx.annotation:annotation:1.8.1")
testRuntimeOnly(SdkHelperKt.getSdkDependency(project))
testRuntimeOnly(libs.intellijAnnotations)
testRuntimeOnly(libs.jsr250)
diff --git a/room/integration-tests/multiplatformtestapp/src/jvmTest/kotlin/androidx/room/integration/multiplatformtestapp/test/JvmOnlyDatabaseDeclarationTest.kt b/room/integration-tests/multiplatformtestapp/src/jvmTest/kotlin/androidx/room/integration/multiplatformtestapp/test/JvmOnlyDatabaseDeclarationTest.kt
new file mode 100644
index 0000000..d716001
--- /dev/null
+++ b/room/integration-tests/multiplatformtestapp/src/jvmTest/kotlin/androidx/room/integration/multiplatformtestapp/test/JvmOnlyDatabaseDeclarationTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 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 androidx.room.integration.multiplatformtestapp.test
+
+import androidx.kruth.assertThat
+import androidx.room.Database
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.room.useReaderConnection
+import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import kotlin.test.Test
+import kotlinx.coroutines.test.runTest
+
+/**
+ * This test validates that a [Database] declared in the Jvm source set does not required the usage
+ * of [androidx.room.ConstructedBy] nor [androidx.room.RoomDatabaseConstructor].
+ */
+class JvmOnlyDatabaseDeclarationTest {
+
+ @Test
+ fun buildJvmOnlyRoomDatabase() = runTest {
+ val database =
+ Room.inMemoryDatabaseBuilder<TestDatabase>().setDriver(BundledSQLiteDriver()).build()
+ val dbVersion =
+ database.useReaderConnection { connection ->
+ connection.usePrepared("PRAGMA user_version") {
+ it.step()
+ it.getLong(0)
+ }
+ }
+ assertThat(dbVersion).isEqualTo(1)
+ }
+
+ @Database(entities = [TestEntity::class], version = 1, exportSchema = false)
+ abstract class TestDatabase : RoomDatabase()
+
+ @Entity data class TestEntity(@PrimaryKey val id: Long)
+}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
index f57ed83..7c0e658 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/ext/xpoet_ext.kt
@@ -222,20 +222,39 @@
}
object RoomRxJava2TypeNames {
- val RX_ROOM = XClassName.get(ROOM_PACKAGE, "RxRoom")
- val RX_ROOM_CREATE_FLOWABLE = "createFlowable"
- val RX_ROOM_CREATE_OBSERVABLE = "createObservable"
- val RX_EMPTY_RESULT_SET_EXCEPTION = XClassName.get(ROOM_PACKAGE, "EmptyResultSetException")
+ val RX2_ROOM = XClassName.get(ROOM_PACKAGE, "RxRoom")
+ val RX2_EMPTY_RESULT_SET_EXCEPTION = XClassName.get(ROOM_PACKAGE, "EmptyResultSetException")
+}
+
+object RoomRxJava2MemberNames {
+ val RX_ROOM_CREATE_FLOWABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createFlowable", isJvmStatic = true)
+ val RX_ROOM_CREATE_OBSERVABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createObservable", isJvmStatic = true)
+ val RX_ROOM_CREATE_SINGLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createSingle", isJvmStatic = true)
+ val RX_ROOM_CREATE_MAYBE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createMaybe", isJvmStatic = true)
+ val RX_ROOM_CREATE_COMPLETABLE =
+ RoomRxJava2TypeNames.RX2_ROOM.companionMember("createCompletable", isJvmStatic = true)
}
object RoomRxJava3TypeNames {
- val RX_ROOM = XClassName.get("$ROOM_PACKAGE.rxjava3", "RxRoom")
- val RX_ROOM_CREATE_FLOWABLE = "createFlowable"
- val RX_ROOM_CREATE_OBSERVABLE = "createObservable"
- val RX_EMPTY_RESULT_SET_EXCEPTION =
+ val RX3_ROOM = XClassName.get("$ROOM_PACKAGE.rxjava3", "RxRoom")
+ val RX3_ROOM_MARKER = XClassName.get("$ROOM_PACKAGE.rxjava3", "Rx3RoomArtifactMarker")
+ val RX3_EMPTY_RESULT_SET_EXCEPTION =
XClassName.get("$ROOM_PACKAGE.rxjava3", "EmptyResultSetException")
}
+object RoomRxJava3MemberNames {
+ val RX_ROOM_CREATE_FLOWABLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createFlowable")
+ val RX_ROOM_CREATE_OBSERVABLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createObservable")
+ val RX_ROOM_CREATE_SINGLE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createSingle")
+ val RX_ROOM_CREATE_MAYBE = RoomRxJava3TypeNames.RX3_ROOM.packageMember("createMaybe")
+ val RX_ROOM_CREATE_COMPLETABLE =
+ RoomRxJava3TypeNames.RX3_ROOM.packageMember("createCompletable")
+}
+
object RoomPagingTypeNames {
val LIMIT_OFFSET_PAGING_SOURCE =
XClassName.get("$ROOM_PACKAGE.paging", "LimitOffsetPagingSource")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
index 8d375ac..3909425 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/Context.kt
@@ -323,4 +323,10 @@
targetPlatforms.contains(XProcessingEnv.Platform.JVM) &&
this.processingEnv.findType("android.content.Context") != null
}
+
+ /** Check if the target platform is JVM. */
+ fun isJvmOnlyTarget(): Boolean {
+ val targetPlatforms = this.processingEnv.targetPlatforms
+ return targetPlatforms.size == 1 && targetPlatforms.contains(XProcessingEnv.Platform.JVM)
+ }
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index 7f1f632..b49a6c2 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -546,8 +546,11 @@
private fun processConstructorObject(element: XTypeElement): XTypeElement? {
val annotation = element.getAnnotation(androidx.room.ConstructedBy::class)
if (annotation == null) {
+ // If no @ConstructedBy is present then validate target is JVM (including Android)
+ // since reflection is available in those platforms and a database constructor is not
+ // needed.
context.checker.check(
- predicate = context.isAndroidOnlyTarget(),
+ predicate = context.isJvmOnlyTarget(),
element = element,
errorMsg = ProcessorErrors.MISSING_CONSTRUCTED_BY_ANNOTATION
)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
index 762028e..b6b1fd6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/RxTypes.kt
@@ -17,7 +17,10 @@
package androidx.room.solver
import androidx.room.compiler.codegen.XClassName
+import androidx.room.compiler.codegen.XMemberName
+import androidx.room.ext.RoomRxJava2MemberNames
import androidx.room.ext.RoomRxJava2TypeNames
+import androidx.room.ext.RoomRxJava3MemberNames
import androidx.room.ext.RoomRxJava3TypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
@@ -26,54 +29,80 @@
internal enum class RxType(
val version: RxVersion,
val className: XClassName,
- val factoryMethodName: String? = null,
+ val factoryMethodName: XMemberName,
val canBeNull: Boolean = false
) {
// RxJava2 types
RX2_FLOWABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_FLOWABLE
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_FLOWABLE
),
RX2_OBSERVABLE(
version = RxVersion.TWO,
className = RxJava2TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava2TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_OBSERVABLE
),
- RX2_SINGLE(version = RxVersion.TWO, className = RxJava2TypeNames.SINGLE),
- RX2_MAYBE(version = RxVersion.TWO, className = RxJava2TypeNames.MAYBE, canBeNull = true),
- RX2_COMPLETABLE(version = RxVersion.TWO, className = RxJava2TypeNames.COMPLETABLE),
+ RX2_SINGLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.SINGLE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_SINGLE
+ ),
+ RX2_MAYBE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.MAYBE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_MAYBE,
+ canBeNull = true
+ ),
+ RX2_COMPLETABLE(
+ version = RxVersion.TWO,
+ className = RxJava2TypeNames.COMPLETABLE,
+ factoryMethodName = RoomRxJava2MemberNames.RX_ROOM_CREATE_COMPLETABLE
+ ),
// RxJava3 types
RX3_FLOWABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.FLOWABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_FLOWABLE
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_FLOWABLE
),
RX3_OBSERVABLE(
version = RxVersion.THREE,
className = RxJava3TypeNames.OBSERVABLE,
- factoryMethodName = RoomRxJava3TypeNames.RX_ROOM_CREATE_OBSERVABLE
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_OBSERVABLE
),
- RX3_SINGLE(version = RxVersion.THREE, className = RxJava3TypeNames.SINGLE),
- RX3_MAYBE(version = RxVersion.THREE, className = RxJava3TypeNames.MAYBE, canBeNull = true),
- RX3_COMPLETABLE(version = RxVersion.THREE, className = RxJava3TypeNames.COMPLETABLE);
+ RX3_SINGLE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.SINGLE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_SINGLE
+ ),
+ RX3_MAYBE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.MAYBE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_MAYBE,
+ canBeNull = true
+ ),
+ RX3_COMPLETABLE(
+ version = RxVersion.THREE,
+ className = RxJava3TypeNames.COMPLETABLE,
+ factoryMethodName = RoomRxJava3MemberNames.RX_ROOM_CREATE_COMPLETABLE
+ );
fun isSingle() = this == RX2_SINGLE || this == RX3_SINGLE
}
internal enum class RxVersion(
- val rxRoomClassName: XClassName,
+ val rxMarkerClassName: XClassName,
val emptyResultExceptionClassName: XClassName,
val missingArtifactMessage: String
) {
TWO(
- rxRoomClassName = RoomRxJava2TypeNames.RX_ROOM,
- emptyResultExceptionClassName = RoomRxJava2TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ rxMarkerClassName = RoomRxJava2TypeNames.RX2_ROOM,
+ emptyResultExceptionClassName = RoomRxJava2TypeNames.RX2_EMPTY_RESULT_SET_EXCEPTION,
missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA2_ARTIFACT
),
THREE(
- rxRoomClassName = RoomRxJava3TypeNames.RX_ROOM,
- emptyResultExceptionClassName = RoomRxJava3TypeNames.RX_EMPTY_RESULT_SET_EXCEPTION,
+ rxMarkerClassName = RoomRxJava3TypeNames.RX3_ROOM_MARKER,
+ emptyResultExceptionClassName = RoomRxJava3TypeNames.RX3_EMPTY_RESULT_SET_EXCEPTION,
missingArtifactMessage = ProcessorErrors.MISSING_ROOM_RXJAVA3_ARTIFACT
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index 4523c50..abe96e5 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -54,9 +54,9 @@
import androidx.room.solver.binderprovider.ListenableFuturePagingSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
-import androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxJava2PagingSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxJava3PagingSourceQueryResultBinderProvider
+import androidx.room.solver.binderprovider.RxLambdaQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
import androidx.room.solver.prepared.binderprovider.GuavaListenableFuturePreparedQueryResultBinderProvider
@@ -208,7 +208,7 @@
add(LiveDataQueryResultBinderProvider(context))
add(GuavaListenableFutureQueryResultBinderProvider(context))
addAll(RxQueryResultBinderProvider.getAll(context))
- addAll(RxCallableQueryResultBinderProvider.getAll(context))
+ addAll(RxLambdaQueryResultBinderProvider.getAll(context))
add(DataSourceQueryResultBinderProvider(context))
add(DataSourceFactoryQueryResultBinderProvider(context))
add(RxJava2PagingSourceQueryResultBinderProvider(context))
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
similarity index 89%
rename from room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
rename to room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
index 129241d..701cf87 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxCallableQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxLambdaQueryResultBinderProvider.kt
@@ -24,9 +24,9 @@
import androidx.room.solver.RxType
import androidx.room.solver.TypeAdapterExtras
import androidx.room.solver.query.result.QueryResultBinder
-import androidx.room.solver.query.result.RxCallableQueryResultBinder
+import androidx.room.solver.query.result.RxLambdaQueryResultBinder
-class RxCallableQueryResultBinderProvider
+class RxLambdaQueryResultBinderProvider
private constructor(val context: Context, private val rxType: RxType) : QueryResultBinderProvider {
override fun provide(
declared: XType,
@@ -40,7 +40,7 @@
)
val typeArg = extractTypeArg(declared)
val adapter = context.typeAdapterStore.findQueryResultAdapter(typeArg, query, extras)
- return RxCallableQueryResultBinder(rxType, typeArg, adapter)
+ return RxLambdaQueryResultBinder(rxType, typeArg, adapter)
}
override fun matches(declared: XType): Boolean =
@@ -62,10 +62,10 @@
companion object {
fun getAll(context: Context) =
listOf(RxType.RX2_SINGLE, RxType.RX2_MAYBE, RxType.RX3_SINGLE, RxType.RX3_MAYBE).map {
- RxCallableQueryResultBinderProvider(context, it)
+ RxLambdaQueryResultBinderProvider(context, it)
.requireArtifact(
context = context,
- requiredType = it.version.rxRoomClassName,
+ requiredType = it.version.rxMarkerClassName,
missingArtifactErrorMsg = it.version.missingArtifactMessage
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
index a592faaf..aad54a6 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/binderprovider/RxQueryResultBinderProvider.kt
@@ -25,6 +25,7 @@
import androidx.room.solver.query.result.QueryResultBinder
import androidx.room.solver.query.result.RxQueryResultBinder
+/** Generic result binder for Rx classes that are reactive. */
class RxQueryResultBinderProvider
private constructor(context: Context, private val rxType: RxType) :
ObservableQueryResultBinderProvider(context) {
@@ -69,7 +70,7 @@
RxQueryResultBinderProvider(context, it)
.requireArtifact(
context = context,
- requiredType = it.version.rxRoomClassName,
+ requiredType = it.version.rxMarkerClassName,
missingArtifactErrorMsg = it.version.missingArtifactMessage
)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt
deleted file mode 100644
index 622bb16..0000000
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binder/CallablePreparedQueryResultBinder.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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 androidx.room.solver.prepared.binder
-
-import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XPropertySpec
-import androidx.room.compiler.codegen.XTypeSpec
-import androidx.room.compiler.processing.XType
-import androidx.room.ext.CallableTypeSpecBuilder
-import androidx.room.solver.CodeGenScope
-import androidx.room.solver.prepared.result.PreparedQueryResultAdapter
-
-/**
- * Binder for deferred queries.
- *
- * This binder will create a Callable implementation that delegates to the
- * [PreparedQueryResultAdapter]. Usage of the Callable impl is then delegate to the [addStmntBlock]
- * function.
- */
-class CallablePreparedQueryResultBinder
-private constructor(
- val returnType: XType,
- val addStmntBlock:
- XCodeBlock.Builder.(callableImpl: XTypeSpec, dbProperty: XPropertySpec) -> Unit,
- adapter: PreparedQueryResultAdapter?
-) : PreparedQueryResultBinder(adapter) {
-
- companion object {
- fun createPreparedBinder(
- returnType: XType,
- adapter: PreparedQueryResultAdapter?,
- addCodeBlock:
- XCodeBlock.Builder.(callableImpl: XTypeSpec, dbProperty: XPropertySpec) -> Unit
- ) = CallablePreparedQueryResultBinder(returnType, addCodeBlock, adapter)
- }
-
- override fun executeAndReturn(
- prepareQueryStmtBlock: CodeGenScope.() -> String,
- preparedStmtProperty: XPropertySpec?,
- dbProperty: XPropertySpec,
- scope: CodeGenScope
- ) {
- val binderScope = scope.fork()
- val callableImpl =
- CallableTypeSpecBuilder(scope.language, returnType.asTypeName()) {
- adapter?.executeAndReturn(
- binderScope.prepareQueryStmtBlock(),
- preparedStmtProperty,
- dbProperty,
- binderScope
- )
- addCode(binderScope.generate())
- }
- .build()
-
- scope.builder.apply { addStmntBlock(callableImpl, dbProperty) }
- }
-}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
index 5b5a248..d7153fc 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/prepared/binderprovider/RxPreparedQueryResultBinderProvider.kt
@@ -18,10 +18,11 @@
import androidx.room.compiler.processing.XRawType
import androidx.room.compiler.processing.XType
+import androidx.room.ext.KotlinTypeNames
import androidx.room.parser.ParsedQuery
import androidx.room.processor.Context
import androidx.room.solver.RxType
-import androidx.room.solver.prepared.binder.CallablePreparedQueryResultBinder.Companion.createPreparedBinder
+import androidx.room.solver.prepared.binder.LambdaPreparedQueryResultBinder
import androidx.room.solver.prepared.binder.PreparedQueryResultBinder
open class RxPreparedQueryResultBinderProvider
@@ -29,7 +30,8 @@
PreparedQueryResultBinderProvider {
private val hasRxJavaArtifact by lazy {
- context.processingEnv.findTypeElement(rxType.version.rxRoomClassName.canonicalName) != null
+ context.processingEnv.findTypeElement(rxType.version.rxMarkerClassName.canonicalName) !=
+ null
}
override fun matches(declared: XType): Boolean =
@@ -44,12 +46,11 @@
context.logger.e(rxType.version.missingArtifactMessage)
}
val typeArg = extractTypeArg(declared)
- return createPreparedBinder(
+ return LambdaPreparedQueryResultBinder(
returnType = typeArg,
+ functionName = rxType.factoryMethodName,
adapter = context.typeAdapterStore.findPreparedQueryResultAdapter(typeArg, query)
- ) { callableImpl, _ ->
- addStatement("return %T.fromCallable(%L)", rxType.className, callableImpl)
- }
+ )
}
open fun extractTypeArg(declared: XType): XType = declared.typeArguments.first()
@@ -82,16 +83,17 @@
}
/**
- * Since Completable is not a generic, the supported return type should be Void (nullable). Like
- * this, the generated Callable.call method will return Void.
+ * Since Completable has no type argument, the supported return type is Unit (non-nullable)
+ * since the 'createCompletable" factory method take a Kotlin lambda.
*/
- override fun extractTypeArg(declared: XType): XType = context.COMMON_TYPES.VOID.makeNullable()
+ override fun extractTypeArg(declared: XType): XType =
+ context.processingEnv.requireType(KotlinTypeNames.UNIT)
}
private class RxSingleOrMaybePreparedQueryResultBinderProvider(context: Context, rxType: RxType) :
RxPreparedQueryResultBinderProvider(context, rxType) {
- /** Since Maybe can have null values, the Callable returned must allow for null values. */
+ /** Since Maybe can have null values, the lambda returned must allow for null values. */
override fun extractTypeArg(declared: XType): XType =
declared.typeArguments.first().makeNullable()
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
similarity index 68%
rename from room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
rename to room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
index a16c91f..10973f3 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxLambdaQueryResultBinder.kt
@@ -19,20 +19,25 @@
import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.VisibilityModifier
import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
import androidx.room.compiler.codegen.XFunSpec
import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
import androidx.room.compiler.codegen.XPropertySpec
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.codegen.XTypeSpec
import androidx.room.compiler.processing.XNullability
import androidx.room.compiler.processing.XType
import androidx.room.ext.AndroidTypeNames.CURSOR
import androidx.room.ext.CallableTypeSpecBuilder
+import androidx.room.ext.InvokeWithLambdaParameter
+import androidx.room.ext.LambdaSpec
import androidx.room.ext.RoomMemberNames.DB_UTIL_QUERY
+import androidx.room.ext.SQLiteDriverTypeNames
import androidx.room.solver.CodeGenScope
import androidx.room.solver.RxType
-/** Generic Result binder for Rx classes that accept a callable. */
-internal class RxCallableQueryResultBinder(
+/** Generic result binder for Rx classes that are not reactive. */
+internal class RxLambdaQueryResultBinder(
private val rxType: RxType,
val typeArg: XType,
adapter: QueryResultAdapter?
@@ -68,7 +73,7 @@
.build()
scope.builder.apply {
if (rxType.isSingle()) {
- addStatement("return %T.createSingle(%L)", rxType.version.rxRoomClassName, callable)
+ addStatement("return %M(%L)", rxType.factoryMethodName, callable)
} else {
addStatement("return %T.fromCallable(%L)", rxType.className, callable)
}
@@ -160,4 +165,57 @@
.build()
)
}
+
+ override fun isMigratedToDriver() = adapter?.isMigratedToDriver() == true
+
+ override fun convertAndReturn(
+ sqlQueryVar: String,
+ dbProperty: XPropertySpec,
+ bindStatement: CodeGenScope.(String) -> Unit,
+ returnTypeName: XTypeName,
+ inTransaction: Boolean,
+ scope: CodeGenScope
+ ) {
+ val connectionVar = scope.getTmpVar("_connection")
+ val performBlock =
+ InvokeWithLambdaParameter(
+ scope = scope,
+ functionName = rxType.factoryMethodName,
+ argFormat = listOf("%N", "%L", "%L"),
+ args = listOf(dbProperty, /* isReadOnly= */ true, inTransaction),
+ lambdaSpec =
+ object :
+ LambdaSpec(
+ parameterTypeName = SQLiteDriverTypeNames.CONNECTION,
+ parameterName = connectionVar,
+ returnTypeName = typeArg.asTypeName(),
+ javaLambdaSyntaxAvailable = scope.javaLambdaSyntaxAvailable
+ ) {
+ override fun XCodeBlock.Builder.body(scope: CodeGenScope) {
+ val returnPrefix =
+ when (language) {
+ CodeLanguage.JAVA -> "return "
+ CodeLanguage.KOTLIN -> ""
+ }
+ val statementVar = scope.getTmpVar("_stmt")
+ addLocalVal(
+ statementVar,
+ SQLiteDriverTypeNames.STATEMENT,
+ "%L.prepare(%L)",
+ connectionVar,
+ sqlQueryVar
+ )
+ beginControlFlow("try")
+ bindStatement(scope, statementVar)
+ val outVar = scope.getTmpVar("_result")
+ adapter?.convert(outVar, statementVar, scope)
+ addStatement("$returnPrefix%L", outVar)
+ nextControlFlow("finally")
+ addStatement("%L.close()", statementVar)
+ endControlFlow()
+ }
+ }
+ )
+ scope.builder.add("return %L", performBlock)
+ }
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
index 838c502..bc8877e 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/RxQueryResultBinder.kt
@@ -16,12 +16,18 @@
package androidx.room.solver.query.result
+import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.XCodeBlock
+import androidx.room.compiler.codegen.XCodeBlock.Builder.Companion.addLocalVal
import androidx.room.compiler.codegen.XPropertySpec
+import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.XType
import androidx.room.ext.ArrayLiteral
import androidx.room.ext.CallableTypeSpecBuilder
import androidx.room.ext.CommonTypeNames
+import androidx.room.ext.InvokeWithLambdaParameter
+import androidx.room.ext.LambdaSpec
+import androidx.room.ext.SQLiteDriverTypeNames
import androidx.room.solver.CodeGenScope
import androidx.room.solver.RxType
@@ -69,9 +75,8 @@
*queryTableNames.toTypedArray()
)
addStatement(
- "return %T.%N(%N, %L, %L, %L)",
- rxType.version.rxRoomClassName,
- rxType.factoryMethodName!!,
+ "return %M(%N, %L, %L, %L)",
+ rxType.factoryMethodName,
dbProperty,
if (inTransaction) "true" else "false",
arrayOfTableNamesLiteral,
@@ -79,4 +84,66 @@
)
}
}
+
+ override fun isMigratedToDriver() = adapter?.isMigratedToDriver() ?: false
+
+ override fun convertAndReturn(
+ sqlQueryVar: String,
+ dbProperty: XPropertySpec,
+ bindStatement: CodeGenScope.(String) -> Unit,
+ returnTypeName: XTypeName,
+ inTransaction: Boolean,
+ scope: CodeGenScope
+ ) {
+ val connectionVar = scope.getTmpVar("_connection")
+ val performBlock =
+ InvokeWithLambdaParameter(
+ scope = scope,
+ functionName = rxType.factoryMethodName,
+ argFormat = listOf("%N", "%L", "%L"),
+ args =
+ listOf(
+ dbProperty,
+ inTransaction,
+ ArrayLiteral(
+ scope.language,
+ CommonTypeNames.STRING,
+ *queryTableNames.toTypedArray()
+ )
+ ),
+ lambdaSpec =
+ object :
+ LambdaSpec(
+ parameterTypeName = SQLiteDriverTypeNames.CONNECTION,
+ parameterName = connectionVar,
+ returnTypeName = typeArg.asTypeName(),
+ javaLambdaSyntaxAvailable = scope.javaLambdaSyntaxAvailable
+ ) {
+ override fun XCodeBlock.Builder.body(scope: CodeGenScope) {
+ val returnPrefix =
+ when (language) {
+ CodeLanguage.JAVA -> "return "
+ CodeLanguage.KOTLIN -> ""
+ }
+ val statementVar = scope.getTmpVar("_stmt")
+ addLocalVal(
+ statementVar,
+ SQLiteDriverTypeNames.STATEMENT,
+ "%L.prepare(%L)",
+ connectionVar,
+ sqlQueryVar
+ )
+ beginControlFlow("try")
+ bindStatement(scope, statementVar)
+ val outVar = scope.getTmpVar("_result")
+ adapter?.convert(outVar, statementVar, scope)
+ addStatement("$returnPrefix%L", outVar)
+ nextControlFlow("finally")
+ addStatement("%L.close()", statementVar)
+ endControlFlow()
+ }
+ }
+ )
+ scope.builder.add("return %L", performBlock)
+ }
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableDeleteOrUpdateMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableDeleteOrUpdateMethodBinder.kt
deleted file mode 100644
index 58f383f..0000000
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableDeleteOrUpdateMethodBinder.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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 androidx.room.solver.shortcut.binder
-
-import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XPropertySpec
-import androidx.room.compiler.codegen.XTypeSpec
-import androidx.room.compiler.processing.XType
-import androidx.room.ext.CallableTypeSpecBuilder
-import androidx.room.solver.CodeGenScope
-import androidx.room.solver.shortcut.result.DeleteOrUpdateMethodAdapter
-import androidx.room.vo.ShortcutQueryParameter
-
-/**
- * Binder for deferred delete and update methods.
- *
- * This binder will create a Callable implementation that delegates to the
- * [DeleteOrUpdateMethodAdapter]. Usage of the Callable impl is then delegate to the [addStmntBlock]
- * function.
- */
-class CallableDeleteOrUpdateMethodBinder
-private constructor(
- val typeArg: XType,
- val addStmntBlock: XCodeBlock.Builder.(callableImpl: XTypeSpec, dbField: XPropertySpec) -> Unit,
- adapter: DeleteOrUpdateMethodAdapter?
-) : DeleteOrUpdateMethodBinder(adapter) {
-
- companion object {
- fun createDeleteOrUpdateBinder(
- typeArg: XType,
- adapter: DeleteOrUpdateMethodAdapter?,
- addCodeBlock:
- XCodeBlock.Builder.(callableImpl: XTypeSpec, dbField: XPropertySpec) -> Unit
- ) = CallableDeleteOrUpdateMethodBinder(typeArg, addCodeBlock, adapter)
- }
-
- override fun convertAndReturn(
- parameters: List<ShortcutQueryParameter>,
- adapters: Map<String, Pair<XPropertySpec, XTypeSpec>>,
- dbProperty: XPropertySpec,
- scope: CodeGenScope
- ) {
- convertAndReturnCompat(parameters, adapters, dbProperty, scope)
- }
-
- override fun convertAndReturnCompat(
- parameters: List<ShortcutQueryParameter>,
- adapters: Map<String, Pair<XPropertySpec, XTypeSpec>>,
- dbProperty: XPropertySpec,
- scope: CodeGenScope
- ) {
- val adapterScope = scope.fork()
- val callableImpl =
- CallableTypeSpecBuilder(scope.language, typeArg.asTypeName()) {
- adapter?.generateMethodBodyCompat(
- parameters = parameters,
- adapters = adapters,
- dbProperty = dbProperty,
- scope = adapterScope
- )
- addCode(adapterScope.generate())
- }
- .build()
-
- scope.builder.apply { addStmntBlock(callableImpl, dbProperty) }
- }
-}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertOrUpsertMethodBinder.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertOrUpsertMethodBinder.kt
deleted file mode 100644
index 7dee268..0000000
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binder/CallableInsertOrUpsertMethodBinder.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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 androidx.room.solver.shortcut.binder
-
-import androidx.room.compiler.codegen.XCodeBlock
-import androidx.room.compiler.codegen.XPropertySpec
-import androidx.room.compiler.codegen.XTypeSpec
-import androidx.room.compiler.processing.XType
-import androidx.room.ext.CallableTypeSpecBuilder
-import androidx.room.solver.CodeGenScope
-import androidx.room.solver.shortcut.result.InsertOrUpsertMethodAdapter
-import androidx.room.vo.ShortcutQueryParameter
-
-/**
- * Binder for deferred insert methods.
- *
- * This binder will create a Callable implementation that delegates to the
- * [InsertOrUpsertMethodAdapter]. Usage of the Callable impl is then delegate to the [addStmntBlock]
- * function.
- */
-class CallableInsertOrUpsertMethodBinder(
- val typeArg: XType,
- val addStmntBlock: XCodeBlock.Builder.(callableImpl: XTypeSpec, dbField: XPropertySpec) -> Unit,
- adapter: InsertOrUpsertMethodAdapter?
-) : InsertOrUpsertMethodBinder(adapter) {
-
- companion object {
- fun createInsertOrUpsertBinder(
- typeArg: XType,
- adapter: InsertOrUpsertMethodAdapter?,
- addCodeBlock:
- XCodeBlock.Builder.(callableImpl: XTypeSpec, dbField: XPropertySpec) -> Unit
- ) = CallableInsertOrUpsertMethodBinder(typeArg, addCodeBlock, adapter)
- }
-
- override fun convertAndReturn(
- parameters: List<ShortcutQueryParameter>,
- adapters: Map<String, Pair<XPropertySpec, Any>>,
- dbProperty: XPropertySpec,
- scope: CodeGenScope
- ) {
- convertAndReturnCompat(parameters, adapters, dbProperty, scope)
- }
-
- override fun convertAndReturnCompat(
- parameters: List<ShortcutQueryParameter>,
- adapters: Map<String, Pair<XPropertySpec, Any>>,
- dbProperty: XPropertySpec,
- scope: CodeGenScope
- ) {
- val adapterScope = scope.fork()
- val callableImpl =
- CallableTypeSpecBuilder(scope.language, typeArg.asTypeName()) {
- addCode(
- XCodeBlock.builder(language)
- .apply {
- adapter?.generateMethodBodyCompat(
- parameters = parameters,
- adapters = adapters,
- dbProperty = dbProperty,
- scope = adapterScope
- )
- addCode(adapterScope.generate())
- }
- .build()
- )
- }
- .build()
-
- scope.builder.apply { addStmntBlock(callableImpl, dbProperty) }
- }
-}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
index fa50cc4..535e608 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableDeleteOrUpdateMethodBinderProvider.kt
@@ -18,10 +18,11 @@
import androidx.room.compiler.processing.XRawType
import androidx.room.compiler.processing.XType
+import androidx.room.ext.KotlinTypeNames
import androidx.room.processor.Context
import androidx.room.solver.RxType
-import androidx.room.solver.shortcut.binder.CallableDeleteOrUpdateMethodBinder.Companion.createDeleteOrUpdateBinder
import androidx.room.solver.shortcut.binder.DeleteOrUpdateMethodBinder
+import androidx.room.solver.shortcut.binder.LambdaDeleteOrUpdateMethodBinder
/** Provider for Rx Callable binders. */
open class RxCallableDeleteOrUpdateMethodBinderProvider
@@ -44,9 +45,11 @@
override fun provide(declared: XType): DeleteOrUpdateMethodBinder {
val typeArg = extractTypeArg(declared)
val adapter = context.typeAdapterStore.findDeleteOrUpdateAdapter(typeArg)
- return createDeleteOrUpdateBinder(typeArg, adapter) { callableImpl, _ ->
- addStatement("return %T.fromCallable(%L)", rxType.className, callableImpl)
- }
+ return LambdaDeleteOrUpdateMethodBinder(
+ typeArg = typeArg,
+ functionName = rxType.factoryMethodName,
+ adapter = adapter
+ )
}
companion object {
@@ -70,25 +73,24 @@
}
/**
- * Since Completable is not a generic, the supported return type should be Void (nullable). Like
- * this, the generated Callable.call method will return Void.
+ * Since Completable has no type argument, the supported return type is Unit (non-nullable)
+ * since the 'createCompletable" factory method take a Kotlin lambda.
*/
- override fun extractTypeArg(declared: XType): XType = context.COMMON_TYPES.VOID.makeNullable()
+ override fun extractTypeArg(declared: XType): XType =
+ context.processingEnv.requireType(KotlinTypeNames.UNIT)
override fun matches(declared: XType): Boolean = isCompletable(declared)
private fun isCompletable(declared: XType): Boolean {
- if (completableType == null) {
- return false
- }
- return declared.rawType.isAssignableFrom(completableType!!)
+ val completableType = this.completableType ?: return false
+ return declared.rawType.isAssignableFrom(completableType)
}
}
private class RxSingleOrMaybeDeleteOrUpdateMethodBinderProvider(context: Context, rxType: RxType) :
RxCallableDeleteOrUpdateMethodBinderProvider(context, rxType) {
- /** Since Maybe can have null values, the Callable returned must allow for null values. */
+ /** Since Maybe can have null values, the lambda returned must allow for null values. */
override fun extractTypeArg(declared: XType): XType =
declared.typeArguments.first().makeNullable()
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertOrUpsertMethodBinderProvider.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertOrUpsertMethodBinderProvider.kt
index fc23f43..9b0223d 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertOrUpsertMethodBinderProvider.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/shortcut/binderprovider/RxCallableInsertOrUpsertMethodBinderProvider.kt
@@ -18,10 +18,11 @@
import androidx.room.compiler.processing.XRawType
import androidx.room.compiler.processing.XType
+import androidx.room.ext.KotlinTypeNames
import androidx.room.processor.Context
import androidx.room.solver.RxType
-import androidx.room.solver.shortcut.binder.CallableInsertOrUpsertMethodBinder.Companion.createInsertOrUpsertBinder
import androidx.room.solver.shortcut.binder.InsertOrUpsertMethodBinder
+import androidx.room.solver.shortcut.binder.LambdaInsertOrUpsertMethodBinder
import androidx.room.vo.ShortcutQueryParameter
/** Provider for Rx Callable binders. */
@@ -54,9 +55,11 @@
} else {
context.typeAdapterStore.findInsertAdapter(typeArg, params)
}
- return createInsertOrUpsertBinder(typeArg, adapter) { callableImpl, _ ->
- addStatement("return %T.fromCallable(%L)", rxType.className, callableImpl)
- }
+ return LambdaInsertOrUpsertMethodBinder(
+ typeArg = typeArg,
+ functionName = rxType.factoryMethodName,
+ adapter = adapter
+ )
}
companion object {
@@ -80,25 +83,24 @@
}
/**
- * Since Completable is not a generic, the supported return type should be Void (nullable). Like
- * this, the generated Callable.call method will return Void.
+ * Since Completable has no type argument, the supported return type is Unit (non-nullable)
+ * since the 'createCompletable" factory method take a Kotlin lambda.
*/
- override fun extractTypeArg(declared: XType): XType = context.COMMON_TYPES.VOID.makeNullable()
+ override fun extractTypeArg(declared: XType): XType =
+ context.processingEnv.requireType(KotlinTypeNames.UNIT)
override fun matches(declared: XType): Boolean = isCompletable(declared)
private fun isCompletable(declared: XType): Boolean {
- if (completableType == null) {
- return false
- }
- return declared.rawType.isAssignableFrom(completableType!!)
+ val completableType = this.completableType ?: return false
+ return declared.rawType.isAssignableFrom(completableType)
}
}
private class RxSingleOrMaybeInsertOrUpsertMethodBinderProvider(context: Context, rxType: RxType) :
RxCallableInsertOrUpsertMethodBinderProvider(context, rxType) {
- /** Since Maybe can have null values, the Callable returned must allow for null values. */
+ /** Since Maybe can have null values, the lambda returned must allow for null values. */
override fun extractTypeArg(declared: XType): XType =
declared.typeArguments.first().makeNullable()
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 0ebee23..8aa2f41 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -29,6 +29,7 @@
import androidx.room.compiler.processing.isTypeElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.GuavaUtilConcurrentTypeNames
@@ -697,15 +698,20 @@
listOf(COMMON.RX2_FLOWABLE to COMMON.RX2_ROOM, COMMON.RX3_FLOWABLE to COMMON.RX3_ROOM)
.forEach { (rxTypeSrc, rxRoomSrc) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val publisher =
@@ -731,15 +737,20 @@
)
.forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val flowable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
@@ -761,15 +772,22 @@
)
.forEach { (rxTypeSrc, rxRoomSrc, rxTypeClassName) ->
runProcessorTest(
- sources =
- listOf(
- COMMON.RX2_SINGLE,
- COMMON.RX3_SINGLE,
- COMMON.RX2_FLOWABLE,
- COMMON.RX3_FLOWABLE,
- COMMON.PUBLISHER,
- rxTypeSrc,
- rxRoomSrc
+ sources = listOf(rxTypeSrc, rxRoomSrc),
+ classpath =
+ compileFiles(
+ listOf(
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_FLOWABLE,
+ COMMON.PUBLISHER,
+ )
)
) { invocation ->
val observable = invocation.processingEnv.requireTypeElement(rxTypeClassName)
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index 7f3e54e..95c2eb0 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -31,8 +31,6 @@
import androidx.room.ext.KotlinTypeNames
import androidx.room.ext.LifecyclesTypeNames
import androidx.room.ext.ReactiveStreamsTypeNames
-import androidx.room.ext.RoomRxJava2TypeNames
-import androidx.room.ext.RoomRxJava3TypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
import androidx.room.processor.DatabaseViewProcessor
@@ -123,9 +121,7 @@
)
}
- val RX2_ROOM by lazy {
- loadJavaCode("common/input/Rx2Room.java", RoomRxJava2TypeNames.RX_ROOM.canonicalName)
- }
+ val RX2_ROOM by lazy { loadKotlinCode("common/input/Rx2Room.kt") }
val RX3_FLOWABLE by lazy {
loadJavaCode("common/input/rxjava3/Flowable.java", RxJava3TypeNames.FLOWABLE.canonicalName)
@@ -150,9 +146,7 @@
)
}
- val RX3_ROOM by lazy {
- loadJavaCode("common/input/Rx3Room.java", RoomRxJava3TypeNames.RX_ROOM.canonicalName)
- }
+ val RX3_ROOM by lazy { loadKotlinCode("common/input/Rx3Room.kt") }
val DATA_SOURCE_FACTORY by lazy { loadKotlinCode("common/input/DataSource.kt") }
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
index 02646fd..b6130b5 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
@@ -1982,18 +1982,6 @@
@Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
fun getMaybe(vararg arg: String?): Maybe<MyEntity>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getObservableNullable(vararg arg: String?): Observable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getSingleNullable(vararg arg: String?): Single<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?>
}
@Entity
@@ -2010,13 +1998,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX2_ROOM,
- COMMON.RX2_FLOWABLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX2_SINGLE,
- COMMON.RX2_MAYBE,
- COMMON.PUBLISHER,
- COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX2_ROOM,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2044,18 +2038,6 @@
@Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
fun getMaybe(vararg arg: String?): Maybe<MyEntity>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getObservableNullable(vararg arg: String?): Observable<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getSingleNullable(vararg arg: String?): Single<MyEntity?>
-
- @Query("SELECT * FROM MyEntity WHERE pk IN (:arg)")
- fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?>
}
@Entity
@@ -2072,13 +2054,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX3_ROOM,
- COMMON.RX3_FLOWABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.RX3_SINGLE,
- COMMON.RX3_MAYBE,
- COMMON.PUBLISHER,
- COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX3_ROOM,
+ COMMON.RX3_FLOWABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2119,14 +2107,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX2_ROOM,
- COMMON.RX2_FLOWABLE,
- COMMON.RX2_OBSERVABLE,
- COMMON.RX2_SINGLE,
- COMMON.RX2_MAYBE,
- COMMON.RX2_COMPLETABLE,
- COMMON.PUBLISHER,
- COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX2_ROOM,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2167,14 +2160,19 @@
listOf(
src,
databaseSrc,
- COMMON.RX3_ROOM,
- COMMON.RX3_FLOWABLE,
- COMMON.RX3_OBSERVABLE,
- COMMON.RX3_SINGLE,
- COMMON.RX3_MAYBE,
- COMMON.RX3_COMPLETABLE,
- COMMON.PUBLISHER,
- COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ ),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX3_ROOM,
+ COMMON.RX3_FLOWABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.PUBLISHER,
+ COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2286,13 +2284,19 @@
.trimIndent()
)
runTest(
- sources =
- listOf(
- src,
- databaseSrc,
- COMMON.RX2_SINGLE,
- COMMON.RX2_COMPLETABLE,
- COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION,
+ sources = listOf(src, databaseSrc),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX2_ROOM,
+ COMMON.RX2_SINGLE,
+ COMMON.RX2_MAYBE,
+ COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_FLOWABLE,
+ COMMON.RX2_OBSERVABLE,
+ COMMON.RX2_EMPTY_RESULT_SET_EXCEPTION,
+ COMMON.PUBLISHER,
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
@@ -2344,13 +2348,19 @@
.trimIndent()
)
runTest(
- sources =
- listOf(
- src,
- databaseSrc,
- COMMON.RX3_SINGLE,
- COMMON.RX3_COMPLETABLE,
- COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION
+ sources = listOf(src, databaseSrc),
+ compiledFiles =
+ compileFiles(
+ listOf(
+ COMMON.RX3_ROOM,
+ COMMON.RX3_SINGLE,
+ COMMON.RX3_MAYBE,
+ COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_FLOWABLE,
+ COMMON.RX3_OBSERVABLE,
+ COMMON.RX3_EMPTY_RESULT_SET_EXCEPTION,
+ COMMON.PUBLISHER,
+ )
),
expectedFilePath = getTestGoldenPath(testName.methodName)
)
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx2Room.java b/room/room-compiler/src/test/test-data/common/input/Rx2Room.java
deleted file mode 100644
index 9e06920..0000000
--- a/room/room-compiler/src/test/test-data/common/input/Rx2Room.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-// mock rx2 helper
-package androidx.room;
-
-import androidx.room.RoomDatabase;
-import java.util.concurrent.Callable;
-import io.reactivex.Flowable;
-import io.reactivex.Observable;
-import io.reactivex.Single;
-public class RxRoom {
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Single<T> createSingle(final Callable<? extends T> callable) {
- return null;
- }
-}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt b/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt
new file mode 100644
index 0000000..771a7c1
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/common/input/Rx2Room.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 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 androidx.room
+
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.Completable
+import io.reactivex.Flowable
+import io.reactivex.Maybe
+import io.reactivex.Observable
+import io.reactivex.Single
+import java.util.concurrent.Callable
+
+// mock rx2 helper
+ class RxRoom {
+
+ companion object {
+
+ @JvmField
+ val NOTHING: Any = Any()
+
+ @JvmStatic
+ fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Flowable<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Observable<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Maybe<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+ ): Completable {
+ TODO()
+ }
+
+ @JvmStatic
+ fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Single<T> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createFlowable(database: RoomDatabase, vararg tableNames: String): Flowable<Any> {
+ TODO()
+ }
+
+ @JvmStatic
+ fun createObservable(database: RoomDatabase, vararg tableNames: String): Observable<Any> {
+ TODO()
+ }
+ }
+}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx3Room.java b/room/room-compiler/src/test/test-data/common/input/Rx3Room.java
deleted file mode 100644
index 518609d..0000000
--- a/room/room-compiler/src/test/test-data/common/input/Rx3Room.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-// mock rx3 helper
-package androidx.room.rxjava3;
-
-import androidx.room.RoomDatabase;
-import java.util.concurrent.Callable;
-import io.reactivex.rxjava3.core.Flowable;
-import io.reactivex.rxjava3.core.Observable;
-import io.reactivex.rxjava3.core.Single;
-
-public class RxRoom {
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- return null;
- }
-
- public static <T> Single<T> createSingle(final Callable<? extends T> callable) {
- return null;
- }
-}
diff --git a/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt b/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt
new file mode 100644
index 0000000..663e479
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/common/input/Rx3Room.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2024 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.
+ */
+
+// mock rx2 helper
+@file:JvmName("RxRoom")
+
+package androidx.room.rxjava3
+
+import androidx.room.RoomDatabase
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.rxjava3.core.Completable
+import io.reactivex.rxjava3.core.Flowable
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.core.Single
+import java.util.concurrent.Callable
+
+class Rx3RoomArtifactMarker private constructor()
+
+@JvmField
+val NOTHING: Any = Any()
+
+fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Flowable<T> {
+ TODO()
+}
+
+fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Observable<T> {
+ TODO()
+}
+
+fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Maybe<T> {
+ TODO()
+}
+
+fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+): Completable {
+ TODO()
+}
+
+fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Single<T> {
+ TODO()
+}
+
+fun createFlowable(
+ database: RoomDatabase,
+ vararg tableNames: String
+): Flowable<Any> {
+ TODO()
+}
+
+fun <T : Any> createFlowable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Flowable<T> {
+ TODO()
+}
+
+fun createObservable(
+ database: RoomDatabase,
+ vararg tableNames: String
+): Observable<Any> {
+ TODO()
+}
+
+fun <T : Any> createObservable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Observable<T> {
+ TODO()
+}
+
+fun <T : Any> createSingle(callable: Callable<out T>): Single<T> {
+ TODO()
+}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/DeletionDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/DeletionDao.java
index 996eaf5..12f1fc8 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/DeletionDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/DeletionDao.java
@@ -1,30 +1,26 @@
package foo.bar;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
import androidx.room.util.SQLiteConnectionUtil;
import androidx.room.util.StringUtil;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
import java.lang.SuppressWarnings;
-import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -33,8 +29,6 @@
private final EntityDeleteOrUpdateAdapter<User> __deleteAdapterOfUser;
- private final EntityDeletionOrUpdateAdapter<User> __deleteCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __deleteAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __deleteAdapterOfBook;
@@ -53,18 +47,6 @@
statement.bindLong(1, entity.uid);
}
};
- this.__deleteCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "DELETE FROM `User` WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement, final User entity) {
- statement.bindLong(1, entity.uid);
- }
- };
this.__deleteAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -164,57 +146,27 @@
@Override
public Completable deleteUserCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ __deleteAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
});
}
@Override
public Single<Integer> deleteUserSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@Override
public Maybe<Integer> deleteUserMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@@ -254,66 +206,48 @@
@Override
public Completable deleteByUidCompletable(final int uid) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return Unit.INSTANCE;
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Single<Integer> deleteByUidSingle(final int uid) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Maybe<Integer> deleteByUidMaybe(final int uid) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/UpdateDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/UpdateDao.java
index 6214715..4f809d6 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/UpdateDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withLambda/UpdateDao.java
@@ -1,27 +1,24 @@
package foo.bar;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
+import androidx.room.util.SQLiteConnectionUtil;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
-import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -32,8 +29,6 @@
private final EntityDeleteOrUpdateAdapter<User> __updateAdapterOfUser_1;
- private final EntityDeletionOrUpdateAdapter<User> __updateCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __updateAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __updateAdapterOfBook;
@@ -88,30 +83,6 @@
statement.bindLong(5, entity.uid);
}
};
- this.__updateCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "UPDATE OR ABORT `User` SET `uid` = ?,`name` = ?,`lastName` = ?,`ageColumn` = ? WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement, final User entity) {
- statement.bindLong(1, entity.uid);
- if (entity.name == null) {
- statement.bindNull(2);
- } else {
- statement.bindString(2, entity.name);
- }
- if (entity.getLastName() == null) {
- statement.bindNull(3);
- } else {
- statement.bindString(3, entity.getLastName());
- }
- statement.bindLong(4, entity.age);
- statement.bindLong(5, entity.uid);
- }
- };
this.__updateAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -232,57 +203,27 @@
@Override
public Completable updateUserAndReturnCountCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ __updateAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
});
}
@Override
public Single<Integer> updateUserAndReturnCountSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@Override
public Maybe<Integer> updateUserAndReturnCountMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@@ -340,60 +281,42 @@
@Override
public Completable ageUserAllCompletable() {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return Unit.INSTANCE;
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Single<Integer> ageUserAllSingle() {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Maybe<Integer> ageUserAllMaybe() {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/DeletionDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/DeletionDao.java
index e287d17..bbbac5e 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/DeletionDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/DeletionDao.java
@@ -3,19 +3,17 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
import androidx.room.util.SQLiteConnectionUtil;
import androidx.room.util.StringUtil;
import androidx.sqlite.SQLiteConnection;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
@@ -24,8 +22,8 @@
import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
import kotlin.jvm.functions.Function1;
@Generated("androidx.room.RoomProcessor")
@@ -35,8 +33,6 @@
private final EntityDeleteOrUpdateAdapter<User> __deleteAdapterOfUser;
- private final EntityDeletionOrUpdateAdapter<User> __deleteCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __deleteAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __deleteAdapterOfBook;
@@ -55,18 +51,6 @@
statement.bindLong(1, entity.uid);
}
};
- this.__deleteCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "DELETE FROM `User` WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement, final User entity) {
- statement.bindLong(1, entity.uid);
- }
- };
this.__deleteAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -194,56 +178,38 @@
@Override
public Completable deleteUserCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
+ return RxRoom.createCompletable(__db, false, true, new Function1<SQLiteConnection, Unit>() {
@Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ @NonNull
+ public Unit invoke(@NonNull final SQLiteConnection _connection) {
+ __deleteAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
}
});
}
@Override
public Single<Integer> deleteUserSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
+ return RxRoom.createSingle(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
}
});
}
@Override
public Maybe<Integer> deleteUserMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
+ return RxRoom.createMaybe(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
}
});
}
@@ -296,21 +262,19 @@
@Override
public Completable deleteByUidCompletable(final int uid) {
- return Completable.fromCallable(new Callable<Void>() {
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createCompletable(__db, false, true, new Function1<SQLiteConnection, Unit>() {
@Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- int _argIndex = 1;
- _stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
+ @NonNull
+ public Unit invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
+ int _argIndex = 1;
+ _stmt.bindLong(_argIndex, uid);
+ _stmt.step();
+ return Unit.INSTANCE;
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
@@ -318,21 +282,19 @@
@Override
public Single<Integer> deleteByUidSingle(final int uid) {
- return Single.fromCallable(new Callable<Integer>() {
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createSingle(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- int _argIndex = 1;
- _stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
+ int _argIndex = 1;
+ _stmt.bindLong(_argIndex, uid);
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
@@ -340,21 +302,19 @@
@Override
public Maybe<Integer> deleteByUidMaybe(final int uid) {
- return Maybe.fromCallable(new Callable<Integer>() {
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createMaybe(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- int _argIndex = 1;
- _stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
+ int _argIndex = 1;
+ _stmt.bindLong(_argIndex, uid);
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/UpdateDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/UpdateDao.java
index f3ca3df..8bbaf88 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/UpdateDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/javac/withoutLambda/UpdateDao.java
@@ -3,17 +3,16 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
+import androidx.room.util.SQLiteConnectionUtil;
import androidx.sqlite.SQLiteConnection;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
@@ -21,8 +20,8 @@
import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
import kotlin.jvm.functions.Function1;
@Generated("androidx.room.RoomProcessor")
@@ -34,8 +33,6 @@
private final EntityDeleteOrUpdateAdapter<User> __updateAdapterOfUser_1;
- private final EntityDeletionOrUpdateAdapter<User> __updateCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __updateAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __updateAdapterOfBook;
@@ -90,30 +87,6 @@
statement.bindLong(5, entity.uid);
}
};
- this.__updateCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "UPDATE OR ABORT `User` SET `uid` = ?,`name` = ?,`lastName` = ?,`ageColumn` = ? WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement, final User entity) {
- statement.bindLong(1, entity.uid);
- if (entity.name == null) {
- statement.bindNull(2);
- } else {
- statement.bindString(2, entity.name);
- }
- if (entity.getLastName() == null) {
- statement.bindNull(3);
- } else {
- statement.bindString(3, entity.getLastName());
- }
- statement.bindLong(4, entity.age);
- statement.bindLong(5, entity.uid);
- }
- };
this.__updateAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -266,56 +239,38 @@
@Override
public Completable updateUserAndReturnCountCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
+ return RxRoom.createCompletable(__db, false, true, new Function1<SQLiteConnection, Unit>() {
@Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ @NonNull
+ public Unit invoke(@NonNull final SQLiteConnection _connection) {
+ __updateAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
}
});
}
@Override
public Single<Integer> updateUserAndReturnCountSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
+ return RxRoom.createSingle(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
}
});
}
@Override
public Maybe<Integer> updateUserAndReturnCountMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
+ return RxRoom.createMaybe(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
}
});
}
@@ -390,19 +345,17 @@
@Override
public Completable ageUserAllCompletable() {
- return Completable.fromCallable(new Callable<Void>() {
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createCompletable(__db, false, true, new Function1<SQLiteConnection, Unit>() {
@Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
+ @NonNull
+ public Unit invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
+ _stmt.step();
+ return Unit.INSTANCE;
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
@@ -410,19 +363,17 @@
@Override
public Single<Integer> ageUserAllSingle() {
- return Single.fromCallable(new Callable<Integer>() {
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createSingle(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
@@ -430,19 +381,17 @@
@Override
public Maybe<Integer> ageUserAllMaybe() {
- return Maybe.fromCallable(new Callable<Integer>() {
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createMaybe(__db, false, true, new Function1<SQLiteConnection, Integer>() {
@Override
@Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
+ public Integer invoke(@NonNull final SQLiteConnection _connection) {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
} finally {
- __db.endTransaction();
+ _stmt.close();
}
}
});
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/DeletionDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/DeletionDao.java
index 4d0654d..d81f936 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/DeletionDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/DeletionDao.java
@@ -1,30 +1,26 @@
package foo.bar;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
import androidx.room.util.SQLiteConnectionUtil;
import androidx.room.util.StringUtil;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
import java.lang.SuppressWarnings;
-import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -33,8 +29,6 @@
private final EntityDeleteOrUpdateAdapter<User> __deleteAdapterOfUser;
- private final EntityDeletionOrUpdateAdapter<User> __deleteCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __deleteAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __deleteAdapterOfBook;
@@ -53,19 +47,6 @@
statement.bindLong(1, entity.uid);
}
};
- this.__deleteCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "DELETE FROM `User` WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement,
- @NonNull final User entity) {
- statement.bindLong(1, entity.uid);
- }
- };
this.__deleteAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -158,57 +139,27 @@
@Override
public Completable deleteUserCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ __deleteAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
});
}
@Override
public Single<Integer> deleteUserSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@Override
public Maybe<Integer> deleteUserMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __deleteCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __deleteAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@@ -248,66 +199,48 @@
@Override
public Completable deleteByUidCompletable(final int uid) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return Unit.INSTANCE;
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Single<Integer> deleteByUidSingle(final int uid) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Maybe<Integer> deleteByUidMaybe(final int uid) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "DELETE FROM user where uid = ?";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
+ final String _sql = "DELETE FROM user where uid = ?";
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
int _argIndex = 1;
_stmt.bindLong(_argIndex, uid);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
diff --git a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/UpdateDao.java b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/UpdateDao.java
index a94f1d5..41ba21c 100644
--- a/room/room-compiler/src/test/test-data/daoWriter/output/ksp/UpdateDao.java
+++ b/room/room-compiler/src/test/test-data/daoWriter/output/ksp/UpdateDao.java
@@ -1,27 +1,24 @@
package foo.bar;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.room.EntityDeleteOrUpdateAdapter;
-import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.RoomDatabase;
+import androidx.room.RxRoom;
import androidx.room.util.DBUtil;
+import androidx.room.util.SQLiteConnectionUtil;
import androidx.sqlite.SQLiteStatement;
-import androidx.sqlite.db.SupportSQLiteStatement;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import java.lang.Class;
-import java.lang.Exception;
import java.lang.Integer;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
-import java.lang.Void;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import javax.annotation.processing.Generated;
+import kotlin.Unit;
@Generated("androidx.room.RoomProcessor")
@SuppressWarnings({"unchecked", "deprecation", "removal"})
@@ -32,8 +29,6 @@
private final EntityDeleteOrUpdateAdapter<User> __updateAdapterOfUser_1;
- private final EntityDeletionOrUpdateAdapter<User> __updateCompatAdapterOfUser;
-
private final EntityDeleteOrUpdateAdapter<MultiPKeyEntity> __updateAdapterOfMultiPKeyEntity;
private final EntityDeleteOrUpdateAdapter<Book> __updateAdapterOfBook;
@@ -88,31 +83,6 @@
statement.bindLong(5, entity.uid);
}
};
- this.__updateCompatAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
- @Override
- @NonNull
- protected String createQuery() {
- return "UPDATE OR ABORT `User` SET `uid` = ?,`name` = ?,`lastName` = ?,`ageColumn` = ? WHERE `uid` = ?";
- }
-
- @Override
- protected void bind(@NonNull final SupportSQLiteStatement statement,
- @NonNull final User entity) {
- statement.bindLong(1, entity.uid);
- if (entity.name == null) {
- statement.bindNull(2);
- } else {
- statement.bindString(2, entity.name);
- }
- if (entity.getLastName() == null) {
- statement.bindNull(3);
- } else {
- statement.bindString(3, entity.getLastName());
- }
- statement.bindLong(4, entity.age);
- statement.bindLong(5, entity.uid);
- }
- };
this.__updateAdapterOfMultiPKeyEntity = new EntityDeleteOrUpdateAdapter<MultiPKeyEntity>() {
@Override
@NonNull
@@ -218,57 +188,27 @@
@Override
public Completable updateUserAndReturnCountCompletable(final User user) {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- __db.beginTransaction();
- try {
- __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ __updateAdapterOfUser.handle(_connection, user);
+ return Unit.INSTANCE;
});
}
@Override
public Single<Integer> updateUserAndReturnCountSingle(final User user) {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@Override
public Maybe<Integer> updateUserAndReturnCountMaybe(final User user) {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- int _total = 0;
- __db.beginTransaction();
- try {
- _total += __updateCompatAdapterOfUser.handle(user);
- __db.setTransactionSuccessful();
- return _total;
- } finally {
- __db.endTransaction();
- }
- }
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ int _result = 0;
+ _result += __updateAdapterOfUser.handle(_connection, user);
+ return _result;
});
}
@@ -326,60 +266,42 @@
@Override
public Completable ageUserAllCompletable() {
- return Completable.fromCallable(new Callable<Void>() {
- @Override
- @Nullable
- public Void call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return null;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createCompletable(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return Unit.INSTANCE;
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Single<Integer> ageUserAllSingle() {
- return Single.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createSingle(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
@Override
public Maybe<Integer> ageUserAllMaybe() {
- return Maybe.fromCallable(new Callable<Integer>() {
- @Override
- @Nullable
- public Integer call() throws Exception {
- final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
- final SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
- __db.beginTransaction();
- try {
- final Integer _result = _stmt.executeUpdateDelete();
- __db.setTransactionSuccessful();
- return _result;
- } finally {
- __db.endTransaction();
- }
+ final String _sql = "UPDATE User SET ageColumn = ageColumn + 1";
+ return RxRoom.createMaybe(__db, false, true, (_connection) -> {
+ final SQLiteStatement _stmt = _connection.prepare(_sql);
+ try {
+ _stmt.step();
+ return SQLiteConnectionUtil.getTotalChangedRows(_connection);
+ } finally {
+ _stmt.close();
}
});
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
index 3ac3f8a..18e3a2b 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx2.kt
@@ -1,17 +1,15 @@
-import android.database.Cursor
-import androidx.room.EmptyResultSetException
import androidx.room.RoomDatabase
-import androidx.room.RoomSQLiteQuery
-import androidx.room.RoomSQLiteQuery.Companion.acquire
-import androidx.room.RxRoom
+import androidx.room.RxRoom.Companion.createFlowable
+import androidx.room.RxRoom.Companion.createMaybe
+import androidx.room.RxRoom.Companion.createObservable
+import androidx.room.RxRoom.Companion.createSingle
import androidx.room.util.appendPlaceholders
import androidx.room.util.getColumnIndexOrThrow
-import androidx.room.util.query
+import androidx.sqlite.SQLiteStatement
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.Observable
import io.reactivex.Single
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.String
@@ -37,43 +35,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createFlowable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getObservable(vararg arg: String?): Observable<MyEntity> {
@@ -83,43 +73,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createObservable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getSingle(vararg arg: String?): Single<MyEntity> {
@@ -129,46 +111,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createSingle(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getMaybe(vararg arg: String?): Maybe<MyEntity> {
@@ -178,230 +149,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createMaybe(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
}
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getObservableNullable(vararg arg: String?): Observable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getSingleNullable(vararg arg: String?): Single<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
}
public companion object {
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
index 491de60..463fa8b 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/callableQuery_rx3.kt
@@ -1,17 +1,15 @@
-import android.database.Cursor
import androidx.room.RoomDatabase
-import androidx.room.RoomSQLiteQuery
-import androidx.room.RoomSQLiteQuery.Companion.acquire
-import androidx.room.rxjava3.EmptyResultSetException
-import androidx.room.rxjava3.RxRoom
+import androidx.room.rxjava3.createFlowable
+import androidx.room.rxjava3.createMaybe
+import androidx.room.rxjava3.createObservable
+import androidx.room.rxjava3.createSingle
import androidx.room.util.appendPlaceholders
import androidx.room.util.getColumnIndexOrThrow
-import androidx.room.util.query
+import androidx.sqlite.SQLiteStatement
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.String
@@ -37,43 +35,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createFlowable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getObservable(vararg arg: String?): Observable<MyEntity> {
@@ -83,43 +73,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity> {
- public override fun call(): MyEntity {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createObservable(__db, false, arrayOf("MyEntity")) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ error("The query result was empty, but expected a single row to return a NON-NULL object of type <MyEntity>.")
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getSingle(vararg arg: String?): Single<MyEntity> {
@@ -129,46 +111,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createSingle(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
+ }
}
public override fun getMaybe(vararg arg: String?): Maybe<MyEntity> {
@@ -178,230 +149,35 @@
appendPlaceholders(_stringBuilder, _inputSize)
_stringBuilder.append(")")
val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
+ return createMaybe(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ var _argIndex: Int = 1
+ for (_item: String? in arg) {
+ if (_item == null) {
+ _stmt.bindNull(_argIndex)
} else {
- _result = null
+ _stmt.bindText(_argIndex, _item)
}
- return _result
- } finally {
- _cursor.close()
+ _argIndex++
}
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_stmt, "other")
+ val _result: MyEntity?
+ if (_stmt.step()) {
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ val _tmpOther: String
+ _tmpOther = _stmt.getText(_cursorIndexOfOther)
+ _result = MyEntity(_tmpPk,_tmpOther)
+ } else {
+ _result = null
+ }
+ _result
+ } finally {
+ _stmt.close()
}
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getFlowableNullable(vararg arg: String?): Flowable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
}
- return RxRoom.createFlowable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getObservableNullable(vararg arg: String?): Observable<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createObservable(__db, false, arrayOf("MyEntity"), object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getSingleNullable(vararg arg: String?): Single<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return RxRoom.createSingle(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- if (_result == null) {
- throw EmptyResultSetException("Query returned empty result set: " + _statement.sql)
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
- }
-
- public override fun getMaybeNullable(vararg arg: String?): Maybe<MyEntity?> {
- val _stringBuilder: StringBuilder = StringBuilder()
- _stringBuilder.append("SELECT * FROM MyEntity WHERE pk IN (")
- val _inputSize: Int = arg.size
- appendPlaceholders(_stringBuilder, _inputSize)
- _stringBuilder.append(")")
- val _sql: String = _stringBuilder.toString()
- val _argCount: Int = 0 + _inputSize
- val _statement: RoomSQLiteQuery = acquire(_sql, _argCount)
- var _argIndex: Int = 1
- for (_item: String? in arg) {
- if (_item == null) {
- _statement.bindNull(_argIndex)
- } else {
- _statement.bindString(_argIndex, _item)
- }
- _argIndex++
- }
- return Maybe.fromCallable(object : Callable<MyEntity?> {
- public override fun call(): MyEntity? {
- val _cursor: Cursor = query(__db, _statement, false, null)
- try {
- val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_cursor, "pk")
- val _cursorIndexOfOther: Int = getColumnIndexOrThrow(_cursor, "other")
- val _result: MyEntity?
- if (_cursor.moveToFirst()) {
- val _tmpPk: Int
- _tmpPk = _cursor.getInt(_cursorIndexOfPk)
- val _tmpOther: String
- _tmpOther = _cursor.getString(_cursorIndexOfOther)
- _result = MyEntity(_tmpPk,_tmpOther)
- } else {
- _result = null
- }
- return _result
- } finally {
- _cursor.close()
- }
- }
-
- protected fun finalize() {
- _statement.release()
- }
- })
}
public companion object {
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx2.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx2.kt
index e3f48cc..fbc5b8f2 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx2.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx2.kt
@@ -1,10 +1,12 @@
import androidx.room.RoomDatabase
-import androidx.sqlite.db.SupportSQLiteStatement
+import androidx.room.RxRoom.Companion.createCompletable
+import androidx.room.RxRoom.Companion.createMaybe
+import androidx.room.RxRoom.Companion.createSingle
+import androidx.room.util.getLastInsertedRowId
+import androidx.sqlite.SQLiteStatement
import io.reactivex.Completable
import io.reactivex.Maybe
import io.reactivex.Single
-import java.lang.Void
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.Long
@@ -23,65 +25,55 @@
this.__db = __db
}
- public override fun insertPublisherSingle(id: String, name: String): Single<Long> =
- Single.fromCallable(object : Callable<Long?> {
- public override fun call(): Long? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherSingle(id: String, name: String): Single<Long> {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createSingle(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _result: Long? = _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return _result
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
+ getLastInsertedRowId(_connection)
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
- public override fun insertPublisherMaybe(id: String, name: String): Maybe<Long> =
- Maybe.fromCallable(object : Callable<Long?> {
- public override fun call(): Long? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherMaybe(id: String, name: String): Maybe<Long> {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createMaybe(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _result: Long? = _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return _result
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
+ getLastInsertedRowId(_connection)
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
- public override fun insertPublisherCompletable(id: String, name: String): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherCompletable(id: String, name: String): Completable {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createCompletable(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return null
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
public companion object {
public fun getRequiredConverters(): List<KClass<*>> = emptyList()
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx3.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx3.kt
index 85d36b7..91a3312 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx3.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/preparedCallableQuery_rx3.kt
@@ -1,10 +1,12 @@
import androidx.room.RoomDatabase
-import androidx.sqlite.db.SupportSQLiteStatement
+import androidx.room.rxjava3.createCompletable
+import androidx.room.rxjava3.createMaybe
+import androidx.room.rxjava3.createSingle
+import androidx.room.util.getLastInsertedRowId
+import androidx.sqlite.SQLiteStatement
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single
-import java.lang.Void
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.Long
@@ -23,65 +25,55 @@
this.__db = __db
}
- public override fun insertPublisherSingle(id: String, name: String): Single<Long> =
- Single.fromCallable(object : Callable<Long?> {
- public override fun call(): Long? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherSingle(id: String, name: String): Single<Long> {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createSingle(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _result: Long? = _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return _result
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
+ getLastInsertedRowId(_connection)
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
- public override fun insertPublisherMaybe(id: String, name: String): Maybe<Long> =
- Maybe.fromCallable(object : Callable<Long?> {
- public override fun call(): Long? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherMaybe(id: String, name: String): Maybe<Long> {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createMaybe(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- val _result: Long? = _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return _result
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
+ getLastInsertedRowId(_connection)
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
- public override fun insertPublisherCompletable(id: String, name: String): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
- val _stmt: SupportSQLiteStatement = __db.compileStatement(_sql)
- var _argIndex: Int = 1
- _stmt.bindString(_argIndex, id)
- _argIndex = 2
- _stmt.bindString(_argIndex, name)
- __db.beginTransaction()
+ public override fun insertPublisherCompletable(id: String, name: String): Completable {
+ val _sql: String = "INSERT INTO MyEntity (pk, other) VALUES (?, ?)"
+ return createCompletable(__db, false, true) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
try {
- _stmt.executeInsert()
- __db.setTransactionSuccessful()
- return null
+ var _argIndex: Int = 1
+ _stmt.bindText(_argIndex, id)
+ _argIndex = 2
+ _stmt.bindText(_argIndex, name)
+ _stmt.step()
} finally {
- __db.endTransaction()
+ _stmt.close()
}
}
- })
+ }
public companion object {
public fun getRequiredConverters(): List<KClass<*>> = emptyList()
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx2.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx2.kt
index 57b5fce..34749e2 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx2.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx2.kt
@@ -1,12 +1,12 @@
-import androidx.room.EntityDeletionOrUpdateAdapter
-import androidx.room.EntityInsertionAdapter
-import androidx.room.EntityUpsertionAdapter
+import androidx.room.EntityDeleteOrUpdateAdapter
+import androidx.room.EntityInsertAdapter
+import androidx.room.EntityUpsertAdapter
import androidx.room.RoomDatabase
-import androidx.sqlite.db.SupportSQLiteStatement
+import androidx.room.RxRoom.Companion.createCompletable
+import androidx.room.RxRoom.Companion.createSingle
+import androidx.sqlite.SQLiteStatement
import io.reactivex.Completable
import io.reactivex.Single
-import java.lang.Void
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.Long
@@ -22,175 +22,109 @@
) : MyDao {
private val __db: RoomDatabase
- private val __insertionAdapterOfMyEntity: EntityInsertionAdapter<MyEntity>
+ private val __insertAdapterOfMyEntity: EntityInsertAdapter<MyEntity>
- private val __deleteCompatAdapterOfMyEntity: EntityDeletionOrUpdateAdapter<MyEntity>
+ private val __deleteAdapterOfMyEntity: EntityDeleteOrUpdateAdapter<MyEntity>
- private val __updateCompatAdapterOfMyEntity: EntityDeletionOrUpdateAdapter<MyEntity>
+ private val __updateAdapterOfMyEntity: EntityDeleteOrUpdateAdapter<MyEntity>
- private val __upsertionAdapterOfMyEntity: EntityUpsertionAdapter<MyEntity>
+ private val __upsertAdapterOfMyEntity: EntityUpsertAdapter<MyEntity>
init {
this.__db = __db
- this.__insertionAdapterOfMyEntity = object : EntityInsertionAdapter<MyEntity>(__db) {
+ this.__insertAdapterOfMyEntity = object : EntityInsertAdapter<MyEntity>() {
protected override fun createQuery(): String =
"INSERT OR ABORT INTO `MyEntity` (`pk`,`other`) VALUES (?,?)"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
}
}
- this.__deleteCompatAdapterOfMyEntity = object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ this.__deleteAdapterOfMyEntity = object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String = "DELETE FROM `MyEntity` WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
}
}
- this.__updateCompatAdapterOfMyEntity = object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ this.__updateAdapterOfMyEntity = object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String =
"UPDATE OR ABORT `MyEntity` SET `pk` = ?,`other` = ? WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
statement.bindLong(3, entity.pk.toLong())
}
}
- this.__upsertionAdapterOfMyEntity = EntityUpsertionAdapter<MyEntity>(object :
- EntityInsertionAdapter<MyEntity>(__db) {
+ this.__upsertAdapterOfMyEntity = EntityUpsertAdapter<MyEntity>(object :
+ EntityInsertAdapter<MyEntity>() {
protected override fun createQuery(): String =
"INSERT INTO `MyEntity` (`pk`,`other`) VALUES (?,?)"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
}
- }, object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ }, object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String =
"UPDATE `MyEntity` SET `pk` = ?,`other` = ? WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
statement.bindLong(3, entity.pk.toLong())
}
})
}
public override fun insertSingle(vararg entities: MyEntity): Single<List<Long>> =
- Single.fromCallable(object : Callable<List<Long>?> {
- public override fun call(): List<Long>? {
- __db.beginTransaction()
- try {
- val _result: List<Long>? = __insertionAdapterOfMyEntity.insertAndReturnIdsList(entities)
- __db.setTransactionSuccessful()
- return _result
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createSingle(__db, false, true) { _connection ->
+ val _result: List<Long>? = __insertAdapterOfMyEntity.insertAndReturnIdsList(_connection,
+ entities)
+ _result
+ }
public override fun insertCompletable(vararg entities: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __insertionAdapterOfMyEntity.insert(entities)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createCompletable(__db, false, true) { _connection ->
+ __insertAdapterOfMyEntity.insert(_connection, entities)
+ }
- public override fun deleteSingle(entity: MyEntity): Single<Int> = Single.fromCallable(object :
- Callable<Int?> {
- public override fun call(): Int? {
- var _total: Int = 0
- __db.beginTransaction()
- try {
- _total += __deleteCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return _total
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun deleteSingle(entity: MyEntity): Single<Int> = createSingle(__db, false, true)
+ { _connection ->
+ var _result: Int = 0
+ _result += __deleteAdapterOfMyEntity.handle(_connection, entity)
+ _result
+ }
- public override fun deleteCompletable(entity: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __deleteCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun deleteCompletable(entity: MyEntity): Completable = createCompletable(__db,
+ false, true) { _connection ->
+ __deleteAdapterOfMyEntity.handle(_connection, entity)
+ }
- public override fun updateSingle(entity: MyEntity): Single<Int> = Single.fromCallable(object :
- Callable<Int?> {
- public override fun call(): Int? {
- var _total: Int = 0
- __db.beginTransaction()
- try {
- _total += __updateCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return _total
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun updateSingle(entity: MyEntity): Single<Int> = createSingle(__db, false, true)
+ { _connection ->
+ var _result: Int = 0
+ _result += __updateAdapterOfMyEntity.handle(_connection, entity)
+ _result
+ }
- public override fun updateCompletable(entity: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __updateCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun updateCompletable(entity: MyEntity): Completable = createCompletable(__db,
+ false, true) { _connection ->
+ __updateAdapterOfMyEntity.handle(_connection, entity)
+ }
public override fun upsertSingle(vararg entities: MyEntity): Single<List<Long>> =
- Single.fromCallable(object : Callable<List<Long>?> {
- public override fun call(): List<Long>? {
- __db.beginTransaction()
- try {
- val _result: List<Long>? = __upsertionAdapterOfMyEntity.upsertAndReturnIdsList(entities)
- __db.setTransactionSuccessful()
- return _result
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createSingle(__db, false, true) { _connection ->
+ val _result: List<Long>? = __upsertAdapterOfMyEntity.upsertAndReturnIdsList(_connection,
+ entities)
+ _result
+ }
public override fun upsertCompletable(vararg entities: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __upsertionAdapterOfMyEntity.upsert(entities)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createCompletable(__db, false, true) { _connection ->
+ __upsertAdapterOfMyEntity.upsert(_connection, entities)
+ }
public companion object {
public fun getRequiredConverters(): List<KClass<*>> = emptyList()
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx3.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx3.kt
index e64428f..6867046 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx3.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/shortcutMethods_rx3.kt
@@ -1,12 +1,12 @@
-import androidx.room.EntityDeletionOrUpdateAdapter
-import androidx.room.EntityInsertionAdapter
-import androidx.room.EntityUpsertionAdapter
+import androidx.room.EntityDeleteOrUpdateAdapter
+import androidx.room.EntityInsertAdapter
+import androidx.room.EntityUpsertAdapter
import androidx.room.RoomDatabase
-import androidx.sqlite.db.SupportSQLiteStatement
+import androidx.room.rxjava3.createCompletable
+import androidx.room.rxjava3.createSingle
+import androidx.sqlite.SQLiteStatement
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
-import java.lang.Void
-import java.util.concurrent.Callable
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.Long
@@ -22,175 +22,109 @@
) : MyDao {
private val __db: RoomDatabase
- private val __insertionAdapterOfMyEntity: EntityInsertionAdapter<MyEntity>
+ private val __insertAdapterOfMyEntity: EntityInsertAdapter<MyEntity>
- private val __deleteCompatAdapterOfMyEntity: EntityDeletionOrUpdateAdapter<MyEntity>
+ private val __deleteAdapterOfMyEntity: EntityDeleteOrUpdateAdapter<MyEntity>
- private val __updateCompatAdapterOfMyEntity: EntityDeletionOrUpdateAdapter<MyEntity>
+ private val __updateAdapterOfMyEntity: EntityDeleteOrUpdateAdapter<MyEntity>
- private val __upsertionAdapterOfMyEntity: EntityUpsertionAdapter<MyEntity>
+ private val __upsertAdapterOfMyEntity: EntityUpsertAdapter<MyEntity>
init {
this.__db = __db
- this.__insertionAdapterOfMyEntity = object : EntityInsertionAdapter<MyEntity>(__db) {
+ this.__insertAdapterOfMyEntity = object : EntityInsertAdapter<MyEntity>() {
protected override fun createQuery(): String =
"INSERT OR ABORT INTO `MyEntity` (`pk`,`other`) VALUES (?,?)"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
}
}
- this.__deleteCompatAdapterOfMyEntity = object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ this.__deleteAdapterOfMyEntity = object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String = "DELETE FROM `MyEntity` WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
}
}
- this.__updateCompatAdapterOfMyEntity = object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ this.__updateAdapterOfMyEntity = object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String =
"UPDATE OR ABORT `MyEntity` SET `pk` = ?,`other` = ? WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
statement.bindLong(3, entity.pk.toLong())
}
}
- this.__upsertionAdapterOfMyEntity = EntityUpsertionAdapter<MyEntity>(object :
- EntityInsertionAdapter<MyEntity>(__db) {
+ this.__upsertAdapterOfMyEntity = EntityUpsertAdapter<MyEntity>(object :
+ EntityInsertAdapter<MyEntity>() {
protected override fun createQuery(): String =
"INSERT INTO `MyEntity` (`pk`,`other`) VALUES (?,?)"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
}
- }, object : EntityDeletionOrUpdateAdapter<MyEntity>(__db) {
+ }, object : EntityDeleteOrUpdateAdapter<MyEntity>() {
protected override fun createQuery(): String =
"UPDATE `MyEntity` SET `pk` = ?,`other` = ? WHERE `pk` = ?"
- protected override fun bind(statement: SupportSQLiteStatement, entity: MyEntity) {
+ protected override fun bind(statement: SQLiteStatement, entity: MyEntity) {
statement.bindLong(1, entity.pk.toLong())
- statement.bindString(2, entity.other)
+ statement.bindText(2, entity.other)
statement.bindLong(3, entity.pk.toLong())
}
})
}
public override fun insertSingle(vararg entities: MyEntity): Single<List<Long>> =
- Single.fromCallable(object : Callable<List<Long>?> {
- public override fun call(): List<Long>? {
- __db.beginTransaction()
- try {
- val _result: List<Long>? = __insertionAdapterOfMyEntity.insertAndReturnIdsList(entities)
- __db.setTransactionSuccessful()
- return _result
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createSingle(__db, false, true) { _connection ->
+ val _result: List<Long>? = __insertAdapterOfMyEntity.insertAndReturnIdsList(_connection,
+ entities)
+ _result
+ }
public override fun insertCompletable(vararg entities: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __insertionAdapterOfMyEntity.insert(entities)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createCompletable(__db, false, true) { _connection ->
+ __insertAdapterOfMyEntity.insert(_connection, entities)
+ }
- public override fun deleteSingle(entity: MyEntity): Single<Int> = Single.fromCallable(object :
- Callable<Int?> {
- public override fun call(): Int? {
- var _total: Int = 0
- __db.beginTransaction()
- try {
- _total += __deleteCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return _total
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun deleteSingle(entity: MyEntity): Single<Int> = createSingle(__db, false, true)
+ { _connection ->
+ var _result: Int = 0
+ _result += __deleteAdapterOfMyEntity.handle(_connection, entity)
+ _result
+ }
- public override fun deleteCompletable(entity: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __deleteCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun deleteCompletable(entity: MyEntity): Completable = createCompletable(__db,
+ false, true) { _connection ->
+ __deleteAdapterOfMyEntity.handle(_connection, entity)
+ }
- public override fun updateSingle(entity: MyEntity): Single<Int> = Single.fromCallable(object :
- Callable<Int?> {
- public override fun call(): Int? {
- var _total: Int = 0
- __db.beginTransaction()
- try {
- _total += __updateCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return _total
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun updateSingle(entity: MyEntity): Single<Int> = createSingle(__db, false, true)
+ { _connection ->
+ var _result: Int = 0
+ _result += __updateAdapterOfMyEntity.handle(_connection, entity)
+ _result
+ }
- public override fun updateCompletable(entity: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __updateCompatAdapterOfMyEntity.handle(entity)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ public override fun updateCompletable(entity: MyEntity): Completable = createCompletable(__db,
+ false, true) { _connection ->
+ __updateAdapterOfMyEntity.handle(_connection, entity)
+ }
public override fun upsertSingle(vararg entities: MyEntity): Single<List<Long>> =
- Single.fromCallable(object : Callable<List<Long>?> {
- public override fun call(): List<Long>? {
- __db.beginTransaction()
- try {
- val _result: List<Long>? = __upsertionAdapterOfMyEntity.upsertAndReturnIdsList(entities)
- __db.setTransactionSuccessful()
- return _result
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createSingle(__db, false, true) { _connection ->
+ val _result: List<Long>? = __upsertAdapterOfMyEntity.upsertAndReturnIdsList(_connection,
+ entities)
+ _result
+ }
public override fun upsertCompletable(vararg entities: MyEntity): Completable =
- Completable.fromCallable(object : Callable<Void?> {
- public override fun call(): Void? {
- __db.beginTransaction()
- try {
- __upsertionAdapterOfMyEntity.upsert(entities)
- __db.setTransactionSuccessful()
- return null
- } finally {
- __db.endTransaction()
- }
- }
- })
+ createCompletable(__db, false, true) { _connection ->
+ __upsertAdapterOfMyEntity.upsert(_connection, entities)
+ }
public companion object {
public fun getRequiredConverters(): List<KClass<*>> = emptyList()
diff --git a/room/room-gradle-plugin/src/test/test-data/multiplatform-project/src/jvmMain/kotlin/room/testapp/MyDatabase.kt b/room/room-gradle-plugin/src/test/test-data/multiplatform-project/src/jvmMain/kotlin/room/testapp/MyDatabase.kt
index 3690e65..c31091d 100644
--- a/room/room-gradle-plugin/src/test/test-data/multiplatform-project/src/jvmMain/kotlin/room/testapp/MyDatabase.kt
+++ b/room/room-gradle-plugin/src/test/test-data/multiplatform-project/src/jvmMain/kotlin/room/testapp/MyDatabase.kt
@@ -19,13 +19,10 @@
import androidx.room.*
@Database(entities = [JvmEntity::class], version = 1)
-@ConstructedBy(MyDatabaseCtor::class)
abstract class MyDatabase : RoomDatabase() {
abstract fun getMyDao(): MyDao
}
-expect object MyDatabaseCtor : RoomDatabaseConstructor<MyDatabase>
-
@Entity
data class JvmEntity(
@PrimaryKey val id: Long
diff --git a/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt b/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
index db0f5ae..7bd8f30 100644
--- a/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
+++ b/room/room-paging-rxjava2/src/main/java/androidx/room/paging/rxjava2/LimitOffsetRxPagingSource.kt
@@ -24,7 +24,7 @@
import androidx.paging.rxjava2.RxPagingSource
import androidx.room.RoomDatabase
import androidx.room.RoomSQLiteQuery
-import androidx.room.RxRoom.createSingle
+import androidx.room.RxRoom
import androidx.room.paging.util.INITIAL_ITEM_COUNT
import androidx.room.paging.util.INVALID
import androidx.room.paging.util.ThreadSafeInvalidationObserver
@@ -56,7 +56,7 @@
override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Value>> {
val scheduler = Schedulers.from(db.queryExecutor)
- return createSingle {
+ return RxRoom.createSingle {
observer.registerIfNecessary(db)
val tempCount = itemCount.get()
if (tempCount == INITIAL_ITEM_COUNT) {
diff --git a/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt b/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
index 6067c44..a2792a0 100644
--- a/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
+++ b/room/room-paging-rxjava3/src/main/java/androidx/room/paging/rxjava3/LimitOffsetRxPagingSource.kt
@@ -30,7 +30,7 @@
import androidx.room.paging.util.getClippedRefreshKey
import androidx.room.paging.util.queryDatabase
import androidx.room.paging.util.queryItemCount
-import androidx.room.rxjava3.RxRoom.createSingle
+import androidx.room.rxjava3.createSingle
import androidx.sqlite.db.SupportSQLiteQuery
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
diff --git a/room/room-rxjava2/api/current.txt b/room/room-rxjava2/api/current.txt
index 73d416e..4df9b3d 100644
--- a/room/room-rxjava2/api/current.txt
+++ b/room/room-rxjava2/api/current.txt
@@ -2,14 +2,20 @@
package androidx.room {
public class EmptyResultSetException extends java.lang.RuntimeException {
- ctor public EmptyResultSetException(String!);
+ ctor public EmptyResultSetException(String message);
}
public class RxRoom {
ctor @Deprecated public RxRoom();
- method public static io.reactivex.Flowable<java.lang.Object!>! createFlowable(androidx.room.RoomDatabase!, java.lang.String!...!);
- method public static io.reactivex.Observable<java.lang.Object!>! createObservable(androidx.room.RoomDatabase!, java.lang.String!...!);
- field public static final Object! NOTHING;
+ method public static final io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method public static final io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ field public static final androidx.room.RxRoom.Companion Companion;
+ field public static final Object NOTHING;
+ }
+
+ public static final class RxRoom.Companion {
+ method public io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method public io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
}
}
diff --git a/room/room-rxjava2/api/restricted_current.txt b/room/room-rxjava2/api/restricted_current.txt
index a3ecfa2..9a2d59c 100644
--- a/room/room-rxjava2/api/restricted_current.txt
+++ b/room/room-rxjava2/api/restricted_current.txt
@@ -2,19 +2,40 @@
package androidx.room {
public class EmptyResultSetException extends java.lang.RuntimeException {
- ctor public EmptyResultSetException(String!);
+ ctor public EmptyResultSetException(String message);
}
public class RxRoom {
ctor @Deprecated public RxRoom();
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.Flowable<T!>! createFlowable(androidx.room.RoomDatabase!, boolean, String![]!, java.util.concurrent.Callable<T!>!);
- method public static io.reactivex.Flowable<java.lang.Object!>! createFlowable(androidx.room.RoomDatabase!, java.lang.String!...!);
- method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.Flowable<T!>! createFlowable(androidx.room.RoomDatabase!, String![]!, java.util.concurrent.Callable<T!>!);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.Observable<T!>! createObservable(androidx.room.RoomDatabase!, boolean, String![]!, java.util.concurrent.Callable<T!>!);
- method public static io.reactivex.Observable<java.lang.Object!>! createObservable(androidx.room.RoomDatabase!, java.lang.String!...!);
- method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.Observable<T!>! createObservable(androidx.room.RoomDatabase!, String![]!, java.util.concurrent.Callable<T!>!);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.Single<T!>! createSingle(java.util.concurrent.Callable<? extends T!>!);
- field public static final Object! NOTHING;
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final io.reactivex.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public static final io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public static final io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static final <T> io.reactivex.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
+ field public static final androidx.room.RxRoom.Companion Companion;
+ field public static final Object NOTHING;
+ }
+
+ public static final class RxRoom.Companion {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public io.reactivex.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public io.reactivex.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Flowable<T> createFlowable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public io.reactivex.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Observable<T> createObservable(androidx.room.RoomDatabase database, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public <T> io.reactivex.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
}
}
diff --git a/room/room-rxjava2/build.gradle b/room/room-rxjava2/build.gradle
index c49ef63..2b23d3f 100644
--- a/room/room-rxjava2/build.gradle
+++ b/room/room-rxjava2/build.gradle
@@ -36,6 +36,7 @@
implementation("androidx.arch.core:core-runtime:2.2.0")
implementation(libs.kotlinStdlib)
+ implementation(libs.kotlinCoroutinesRx2)
testImplementation(project(":kruth:kruth"))
testImplementation(libs.kotlinTest)
diff --git a/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.java b/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.java
deleted file mode 100644
index a36d8a9..0000000
--- a/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 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 androidx.room;
-
-/**
- * Thrown by Room when the query in a Single<T> DAO method needs to return a result but the
- * returned result from the database is empty.
- * <p>
- * Since a Single<T> must either emit a single non-null value or an error, this exception is
- * thrown instead of emitting a null value when the query resulted empty. If the Single<T>
- * contains a type argument of a collection (e.g. Single<List<Song>>) then this
- * exception is not thrown an an empty collection is emitted instead.
- */
-public class EmptyResultSetException extends RuntimeException {
- /**
- * Constructs a new EmptyResultSetException with the exception.
- * @param message The SQL query which didn't return any results.
- */
- public EmptyResultSetException(String message) {
- super(message);
- }
-}
diff --git a/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.kt b/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.kt
new file mode 100644
index 0000000..e2674f6
--- /dev/null
+++ b/room/room-rxjava2/src/main/java/androidx/room/EmptyResultSetException.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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 androidx.room
+
+/**
+ * Thrown by Room when the query in a [io.reactivex.Single] DAO method needs to return a result but
+ * the returned result from the database is empty.
+ *
+ * Since a [io.reactivex.Single] must either emit a single non-null value or an error, this
+ * exception is thrown instead of emitting a null value when the query resulted empty. If the
+ * [io.reactivex.Single] contains a type argument of a collection (e.g. `Single<List<Song>>`) the
+ * this exception is not thrown an an empty collection is emitted instead.
+ */
+open class EmptyResultSetException(message: String) : RuntimeException(message)
diff --git a/room/room-rxjava2/src/main/java/androidx/room/RxRoom.java b/room/room-rxjava2/src/main/java/androidx/room/RxRoom.java
deleted file mode 100644
index 42f3f79..0000000
--- a/room/room-rxjava2/src/main/java/androidx/room/RxRoom.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2017 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 androidx.room;
-
-import android.annotation.SuppressLint;
-
-import androidx.annotation.RestrictTo;
-
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-
-import io.reactivex.BackpressureStrategy;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableEmitter;
-import io.reactivex.FlowableOnSubscribe;
-import io.reactivex.Maybe;
-import io.reactivex.MaybeSource;
-import io.reactivex.Observable;
-import io.reactivex.ObservableEmitter;
-import io.reactivex.ObservableOnSubscribe;
-import io.reactivex.Scheduler;
-import io.reactivex.Single;
-import io.reactivex.SingleEmitter;
-import io.reactivex.SingleOnSubscribe;
-import io.reactivex.disposables.Disposables;
-import io.reactivex.functions.Action;
-import io.reactivex.functions.Function;
-import io.reactivex.schedulers.Schedulers;
-
-/**
- * Helper class to add RxJava2 support to Room.
- */
-@SuppressLint("PrivateConstructorForUtilityClass")
-@SuppressWarnings("WeakerAccess")
-public class RxRoom {
- /**
- * Data dispatched by the publisher created by {@link #createFlowable(RoomDatabase, String...)}.
- */
- public static final Object NOTHING = new Object();
-
- /**
- * Creates a {@link Flowable} that emits at least once and also re-emits whenever one of the
- * observed tables is updated.
- * <p>
- * You can easily chain a database operation to downstream of this {@link Flowable} to ensure
- * that it re-runs when database is modified.
- * <p>
- * Since database invalidation is batched, multiple changes in the database may results in just
- * 1 emission.
- *
- * @param database The database instance
- * @param tableNames The list of table names that should be observed
- * @return A {@link Flowable} which emits {@link #NOTHING} when one of the observed tables
- * is modified (also once when the invalidation tracker connection is established).
- */
- public static Flowable<Object> createFlowable(final RoomDatabase database,
- final String... tableNames) {
- return Flowable.create(new FlowableOnSubscribe<Object>() {
- @Override
- public void subscribe(final FlowableEmitter<Object> emitter) throws Exception {
- final InvalidationTracker.Observer observer = new InvalidationTracker.Observer(
- tableNames) {
- @Override
- public void onInvalidated(@androidx.annotation.NonNull Set<String> tables) {
- if (!emitter.isCancelled()) {
- emitter.onNext(NOTHING);
- }
- }
- };
- if (!emitter.isCancelled()) {
- database.getInvalidationTracker().addObserver(observer);
- emitter.setDisposable(Disposables.fromAction(new Action() {
- @Override
- public void run() throws Exception {
- database.getInvalidationTracker().removeObserver(observer);
- }
- }));
- }
-
- // emit once to avoid missing any data and also easy chaining
- if (!emitter.isCancelled()) {
- emitter.onNext(NOTHING);
- }
- }
- }, BackpressureStrategy.LATEST);
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava2 does not like null.
- *
- * @deprecated Use {@link #createFlowable(RoomDatabase, boolean, String[], Callable)}
- *
- */
- @Deprecated
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final String[] tableNames, final Callable<T> callable) {
- return createFlowable(database, false, tableNames, callable);
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava2 does not like null.
- *
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Flowable<T> createFlowable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- Scheduler scheduler = Schedulers.from(getExecutor(database, inTransaction));
- final Maybe<T> maybe = Maybe.fromCallable(callable);
- return createFlowable(database, tableNames)
- .subscribeOn(scheduler)
- .unsubscribeOn(scheduler)
- .observeOn(scheduler)
- .flatMapMaybe(new Function<Object, MaybeSource<T>>() {
- @Override
- public MaybeSource<T> apply(Object o) throws Exception {
- return maybe;
- }
- });
- }
-
- /**
- * Creates a {@link Observable} that emits at least once and also re-emits whenever one of the
- * observed tables is updated.
- * <p>
- * You can easily chain a database operation to downstream of this {@link Observable} to ensure
- * that it re-runs when database is modified.
- * <p>
- * Since database invalidation is batched, multiple changes in the database may results in just
- * 1 emission.
- *
- * @param database The database instance
- * @param tableNames The list of table names that should be observed
- * @return A {@link Observable} which emits {@link #NOTHING} when one of the observed tables
- * is modified (also once when the invalidation tracker connection is established).
- */
- public static Observable<Object> createObservable(final RoomDatabase database,
- final String... tableNames) {
- return Observable.create(new ObservableOnSubscribe<Object>() {
- @Override
- public void subscribe(final ObservableEmitter<Object> emitter) throws Exception {
- final InvalidationTracker.Observer observer = new InvalidationTracker.Observer(
- tableNames) {
- @Override
- public void onInvalidated(@androidx.annotation.NonNull Set<String> tables) {
- emitter.onNext(NOTHING);
- }
- };
- database.getInvalidationTracker().addObserver(observer);
- emitter.setDisposable(Disposables.fromAction(new Action() {
- @Override
- public void run() throws Exception {
- database.getInvalidationTracker().removeObserver(observer);
- }
- }));
-
- // emit once to avoid missing any data and also easy chaining
- emitter.onNext(NOTHING);
- }
- });
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava2 does not like null.
- *
- * @deprecated Use {@link #createObservable(RoomDatabase, boolean, String[], Callable)}
- *
- */
- @Deprecated
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final String[] tableNames, final Callable<T> callable) {
- return createObservable(database, false, tableNames, callable);
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava2 does not like null.
- *
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Observable<T> createObservable(final RoomDatabase database,
- final boolean inTransaction, final String[] tableNames, final Callable<T> callable) {
- Scheduler scheduler = Schedulers.from(getExecutor(database, inTransaction));
- final Maybe<T> maybe = Maybe.fromCallable(callable);
- return createObservable(database, tableNames)
- .subscribeOn(scheduler)
- .unsubscribeOn(scheduler)
- .observeOn(scheduler)
- .flatMapMaybe(new Function<Object, MaybeSource<T>>() {
- @Override
- public MaybeSource<T> apply(Object o) throws Exception {
- return maybe;
- }
- });
- }
-
- /**
- * Helper method used by generated code to create a Single from a Callable that will ignore
- * the EmptyResultSetException if the stream is already disposed.
- *
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Single<T> createSingle(final Callable<? extends T> callable) {
- return Single.create(new SingleOnSubscribe<T>() {
- @Override
- public void subscribe(SingleEmitter<T> emitter) throws Exception {
- try {
- emitter.onSuccess(callable.call());
- } catch (EmptyResultSetException e) {
- emitter.tryOnError(e);
- }
- }
- });
- }
-
- private static Executor getExecutor(RoomDatabase database, boolean inTransaction) {
- if (inTransaction) {
- return database.getTransactionExecutor();
- } else {
- return database.getQueryExecutor();
- }
- }
-
- /** @deprecated This type should not be instantiated as it contains only static methods. */
- @Deprecated
- @SuppressWarnings("PrivateConstructorForUtilityClass")
- public RxRoom() {
- }
-}
diff --git a/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt b/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt
new file mode 100644
index 0000000..2ae5937
--- /dev/null
+++ b/room/room-rxjava2/src/main/java/androidx/room/RxRoom.kt
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2017 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 androidx.room
+
+import androidx.annotation.RestrictTo
+import androidx.room.coroutines.createFlow
+import androidx.room.util.performBlocking
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.BackpressureStrategy
+import io.reactivex.Completable
+import io.reactivex.Flowable
+import io.reactivex.Maybe
+import io.reactivex.Observable
+import io.reactivex.Single
+import io.reactivex.disposables.Disposables
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.Callable
+import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.rx2.asObservable
+
+open class RxRoom
+@Deprecated("This type should not be instantiated as it contains only utility functions.")
+constructor() {
+
+ companion object {
+
+ /** Data dispatched by the publisher created by [createFlowable]. */
+ @JvmField val NOTHING: Any = Any()
+
+ /** Helper function used by generated code to create a [Flowable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Flowable<T> =
+ createObservable(db, inTransaction, tableNames, block)
+ .toFlowable(BackpressureStrategy.LATEST)
+
+ /** Helper function used by generated code to create a [Observable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+ ): Observable<T> =
+ createFlow(db, inTransaction, tableNames, block)
+ .filterNotNull()
+ .asObservable(db.getQueryContext())
+
+ /** Helper function used by generated code to create a [Maybe] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Maybe<T> = Maybe.fromCallable { performBlocking(db, isReadOnly, inTransaction, block) }
+
+ /** Helper function used by generated code to create a [Completable] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+ ): Completable =
+ Completable.fromAction { performBlocking(db, isReadOnly, inTransaction, block) }
+
+ /** Helper function used by generated code to create a [Single] */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+ ): Single<T> =
+ Single.create { emitter ->
+ if (emitter.isDisposed) return@create
+ try {
+ val result = performBlocking(db, isReadOnly, inTransaction, block)
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+
+ /**
+ * Creates a [Flowable] that emits at least once and also re-emits whenever one of the
+ * observed tables is updated.
+ *
+ * You can easily chain a database operation to downstream of this [Flowable] to ensure that
+ * it re-runs when database is modified.
+ *
+ * Since database invalidation is batched, multiple changes in the database may results in
+ * just 1 emission.
+ *
+ * @param database The database instance
+ * @param tableNames The list of table names that should be observed
+ * @return A [Flowable] which emits [NOTHING] when one of the observed tables is modified
+ * (also once when the invalidation tracker connection is established).
+ */
+ @JvmStatic
+ fun createFlowable(database: RoomDatabase, vararg tableNames: String): Flowable<Any> {
+ return Flowable.create(
+ { emitter ->
+ val observer =
+ object : InvalidationTracker.Observer(tableNames) {
+ override fun onInvalidated(tables: Set<String>) {
+ if (!emitter.isCancelled) {
+ emitter.onNext(NOTHING)
+ }
+ }
+ }
+ if (!emitter.isCancelled) {
+ database.invalidationTracker.addObserver(observer)
+ emitter.setDisposable(
+ Disposables.fromAction {
+ database.invalidationTracker.removeObserver(observer)
+ }
+ )
+ }
+
+ // emit once to avoid missing any data and also easy chaining
+ if (!emitter.isCancelled) {
+ emitter.onNext(NOTHING)
+ }
+ },
+ BackpressureStrategy.LATEST
+ )
+ }
+
+ /**
+ * Helper method used by generated code to bind a [Callable] such that it will be run in our
+ * disk io thread and will automatically block null values since RxJava2 does not like null.
+ */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
+ fun <T : Any> createFlowable(
+ database: RoomDatabase,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+ ): Flowable<T> {
+ @Suppress("DEPRECATION") return createFlowable(database, false, tableNames, callable)
+ }
+
+ /**
+ * Helper method used by generated code to bind a [Callable] such that it will be run in our
+ * disk io thread and will automatically block null values since RxJava2 does not like null.
+ */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
+ fun <T : Any> createFlowable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+ ): Flowable<T> {
+ val scheduler = Schedulers.from(getExecutor(database, inTransaction))
+ val maybe = Maybe.fromCallable(callable)
+ return createFlowable(database, *tableNames)
+ .subscribeOn(scheduler)
+ .unsubscribeOn(scheduler)
+ .observeOn(scheduler)
+ .flatMapMaybe { maybe }
+ }
+
+ /**
+ * Creates a [Observable] that emits at least once and also re-emits whenever one of the
+ * observed tables is updated.
+ *
+ * You can easily chain a database operation to downstream of this [Observable] to ensure
+ * that it re-runs when database is modified.
+ *
+ * Since database invalidation is batched, multiple changes in the database may results in
+ * just 1 emission.
+ *
+ * @param database The database instance
+ * @param tableNames The list of table names that should be observed
+ * @return A [Observable] which emits [.NOTHING] when one of the observed tables is modified
+ * (also once when the invalidation tracker connection is established).
+ */
+ @JvmStatic
+ fun createObservable(database: RoomDatabase, vararg tableNames: String): Observable<Any> {
+ return Observable.create { emitter ->
+ val observer =
+ object : InvalidationTracker.Observer(tableNames) {
+ override fun onInvalidated(tables: Set<String>) {
+ emitter.onNext(NOTHING)
+ }
+ }
+ database.invalidationTracker.addObserver(observer)
+ emitter.setDisposable(
+ Disposables.fromAction { database.invalidationTracker.removeObserver(observer) }
+ )
+
+ // emit once to avoid missing any data and also easy chaining
+ emitter.onNext(NOTHING)
+ }
+ }
+
+ /**
+ * Helper method used by generated code to bind a [Callable] such that it will be run in our
+ * disk io thread and will automatically block null values since RxJava2 does not like null.
+ */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
+ fun <T : Any> createObservable(
+ database: RoomDatabase,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+ ): Observable<T> {
+ @Suppress("DEPRECATION") return createObservable(database, false, tableNames, callable)
+ }
+
+ /**
+ * Helper method used by generated code to bind a [Callable] such that it will be run in our
+ * disk io thread and will automatically block null values since RxJava2 does not like null.
+ */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ @Deprecated("No longer used by generated code.")
+ fun <T : Any> createObservable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+ ): Observable<T> {
+ val scheduler = Schedulers.from(getExecutor(database, inTransaction))
+ val maybe = Maybe.fromCallable(callable)
+ return createObservable(database, *tableNames)
+ .subscribeOn(scheduler)
+ .unsubscribeOn(scheduler)
+ .observeOn(scheduler)
+ .flatMapMaybe { maybe }
+ }
+
+ /**
+ * Helper method used by generated code to create a [Single] from a [Callable] that will
+ * ignore the [EmptyResultSetException] if the stream is already disposed.
+ */
+ @JvmStatic
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+ fun <T : Any> createSingle(callable: Callable<out T>): Single<T> {
+ return Single.create { emitter ->
+ try {
+ val result = callable.call()
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+ }
+
+ private fun getExecutor(database: RoomDatabase, inTransaction: Boolean): Executor {
+ return if (inTransaction) {
+ database.transactionExecutor
+ } else {
+ database.queryExecutor
+ }
+ }
+ }
+}
diff --git a/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt b/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
index 32b23a8..2dcc9d5 100644
--- a/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
+++ b/room/room-rxjava2/src/test/java/androidx/room/RxRoomTest.kt
@@ -21,6 +21,7 @@
import io.reactivex.functions.Consumer
import io.reactivex.observers.TestObserver
import io.reactivex.subscribers.TestSubscriber
+import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import org.junit.Before
@@ -138,12 +139,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Flowable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, false, tables) { value.get() }
+ val flowable = RxRoom.createFlowable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
flowable.subscribe(consumer)
drain()
@@ -167,12 +168,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Observable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createObservable(mDatabase, false, tables) { value.get() }
+ val flowable = RxRoom.createObservable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
flowable.subscribe(consumer)
drain()
@@ -196,11 +197,15 @@
}
@Test
+ @Suppress("DEPRECATION")
fun exception_Flowable() {
val flowable =
- RxRoom.createFlowable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ RxRoom.createFlowable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val subscriber = TestSubscriber<String>()
flowable.subscribe(subscriber)
drain()
@@ -209,11 +214,15 @@
}
@Test
+ @Suppress("DEPRECATION")
fun exception_Observable() {
val flowable =
- RxRoom.createObservable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ RxRoom.createObservable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val observer = TestObserver<String>()
flowable.subscribe(observer)
drain()
diff --git a/room/room-rxjava3/api/current.txt b/room/room-rxjava3/api/current.txt
index 6b78281..bbddba6 100644
--- a/room/room-rxjava3/api/current.txt
+++ b/room/room-rxjava3/api/current.txt
@@ -2,12 +2,12 @@
package androidx.room.rxjava3 {
public final class EmptyResultSetException extends java.lang.RuntimeException {
- ctor public EmptyResultSetException(String);
+ ctor public EmptyResultSetException(String message);
}
public final class RxRoom {
- method public static io.reactivex.rxjava3.core.Flowable<java.lang.Object!> createFlowable(androidx.room.RoomDatabase, java.lang.String!...);
- method public static io.reactivex.rxjava3.core.Observable<java.lang.Object!> createObservable(androidx.room.RoomDatabase, java.lang.String!...);
+ method public static io.reactivex.rxjava3.core.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method public static io.reactivex.rxjava3.core.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
field public static final Object NOTHING;
}
diff --git a/room/room-rxjava3/api/restricted_current.txt b/room/room-rxjava3/api/restricted_current.txt
index 4fb4dbd..9b71011 100644
--- a/room/room-rxjava3/api/restricted_current.txt
+++ b/room/room-rxjava3/api/restricted_current.txt
@@ -2,15 +2,20 @@
package androidx.room.rxjava3 {
public final class EmptyResultSetException extends java.lang.RuntimeException {
- ctor public EmptyResultSetException(String);
+ ctor public EmptyResultSetException(String message);
}
public final class RxRoom {
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T!> createFlowable(androidx.room.RoomDatabase, boolean, String![], java.util.concurrent.Callable<T!>);
- method public static io.reactivex.rxjava3.core.Flowable<java.lang.Object!> createFlowable(androidx.room.RoomDatabase, java.lang.String!...);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T!> createObservable(androidx.room.RoomDatabase, boolean, String![], java.util.concurrent.Callable<T!>);
- method public static io.reactivex.rxjava3.core.Observable<java.lang.Object!> createObservable(androidx.room.RoomDatabase, java.lang.String!...);
- method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Single<T!> createSingle(java.util.concurrent.Callable<? extends T!>);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static io.reactivex.rxjava3.core.Completable createCompletable(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,kotlin.Unit> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T> createFlowable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Flowable<T> createFlowable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public static io.reactivex.rxjava3.core.Flowable<java.lang.Object> createFlowable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Maybe<T> createMaybe(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T> createObservable(androidx.room.RoomDatabase database, boolean inTransaction, String[] tableNames, java.util.concurrent.Callable<? extends T> callable);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Observable<T> createObservable(androidx.room.RoomDatabase db, boolean inTransaction, String[] tableNames, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method public static io.reactivex.rxjava3.core.Observable<java.lang.Object> createObservable(androidx.room.RoomDatabase database, java.lang.String... tableNames);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Single<T> createSingle(androidx.room.RoomDatabase db, boolean isReadOnly, boolean inTransaction, kotlin.jvm.functions.Function1<? super androidx.sqlite.SQLiteConnection,? extends T?> block);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static <T> io.reactivex.rxjava3.core.Single<T> createSingle(java.util.concurrent.Callable<? extends T> callable);
field public static final Object NOTHING;
}
diff --git a/room/room-rxjava3/build.gradle b/room/room-rxjava3/build.gradle
index dd068ad..96c86a1 100644
--- a/room/room-rxjava3/build.gradle
+++ b/room/room-rxjava3/build.gradle
@@ -27,7 +27,6 @@
id("AndroidXPlugin")
id("com.android.library")
id("kotlin-android")
- id("com.google.devtools.ksp")
}
dependencies {
@@ -37,6 +36,7 @@
implementation("androidx.arch.core:core-runtime:2.2.0")
implementation(libs.kotlinStdlib)
+ implementation(libs.kotlinCoroutinesRx3)
testImplementation(project(":kruth:kruth"))
testImplementation(libs.kotlinTest)
diff --git a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.java b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.java
deleted file mode 100644
index 3b2058d..0000000
--- a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 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 androidx.room.rxjava3;
-
-import androidx.annotation.NonNull;
-
-/**
- * Thrown by Room when the query in a Single<T> DAO method needs to return a result but the
- * returned result from the database is empty.
- * <p>
- * Since a Single<T> must either emit a single non-null value or an error, this exception is
- * thrown instead of emitting a null value when the query resulted empty. If the Single<T>
- * contains a type argument of a collection (e.g. Single<List<Song>>) then this
- * exception is not thrown an an empty collection is emitted instead.
- */
-@SuppressWarnings("serial")
-public final class EmptyResultSetException extends RuntimeException {
- /**
- * Constructs a new EmptyResultSetException with the exception.
- * @param message The SQL query which didn't return any results.
- */
- public EmptyResultSetException(@NonNull String message) {
- super(message);
- }
-}
diff --git a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.kt b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.kt
new file mode 100644
index 0000000..b009f6e
--- /dev/null
+++ b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/EmptyResultSetException.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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 androidx.room.rxjava3
+
+/**
+ * Thrown by Room when the query in a [io.reactivex.rxjava3.core.Single] DAO method needs to return
+ * a result but the returned result from the database is empty.
+ *
+ * Since a [io.reactivex.rxjava3.core.Single] must either emit a single non-null value or an error,
+ * this exception is thrown instead of emitting a null value when the query resulted empty. If the
+ * [io.reactivex.rxjava3.core.Single] contains a type argument of a collection (e.g.
+ * `Single<List<Song>>`) the this exception is not thrown an an empty collection is emitted instead.
+ */
+class EmptyResultSetException(message: String) : RuntimeException(message)
diff --git a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.java b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.java
deleted file mode 100644
index e520efd..0000000
--- a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2020 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 androidx.room.rxjava3;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.room.InvalidationTracker;
-import androidx.room.RoomDatabase;
-
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-
-import io.reactivex.rxjava3.core.BackpressureStrategy;
-import io.reactivex.rxjava3.core.Flowable;
-import io.reactivex.rxjava3.core.Maybe;
-import io.reactivex.rxjava3.core.MaybeSource;
-import io.reactivex.rxjava3.core.Observable;
-import io.reactivex.rxjava3.core.Scheduler;
-import io.reactivex.rxjava3.core.Single;
-import io.reactivex.rxjava3.disposables.Disposable;
-import io.reactivex.rxjava3.functions.Function;
-import io.reactivex.rxjava3.schedulers.Schedulers;
-
-/**
- * Helper class to add RxJava3 support to Room.
- */
-public final class RxRoom {
- /**
- * Data dispatched by the publisher created by {@link #createFlowable(RoomDatabase, String...)}.
- */
- @NonNull
- public static final Object NOTHING = new Object();
-
- /**
- * Creates a {@link Flowable} that emits at least once and also re-emits whenever one of the
- * observed tables is updated.
- * <p>
- * You can easily chain a database operation to downstream of this {@link Flowable} to ensure
- * that it re-runs when database is modified.
- * <p>
- * Since database invalidation is batched, multiple changes in the database may results in just
- * 1 emission.
- *
- * @param database The database instance
- * @param tableNames The list of table names that should be observed
- * @return A {@link Flowable} which emits {@link #NOTHING} when one of the observed tables
- * is modified (also once when the invalidation tracker connection is established).
- */
- @NonNull
- public static Flowable<Object> createFlowable(@NonNull final RoomDatabase database,
- @NonNull final String... tableNames) {
- return Flowable.create(emitter -> {
- final InvalidationTracker.Observer observer = new InvalidationTracker.Observer(
- tableNames) {
- @Override
- public void onInvalidated(@androidx.annotation.NonNull Set<String> tables) {
- if (!emitter.isCancelled()) {
- emitter.onNext(NOTHING);
- }
- }
- };
- if (!emitter.isCancelled()) {
- database.getInvalidationTracker().addObserver(observer);
- emitter.setDisposable(Disposable.fromAction(
- () -> database.getInvalidationTracker().removeObserver(observer)));
- }
-
- // emit once to avoid missing any data and also easy chaining
- if (!emitter.isCancelled()) {
- emitter.onNext(NOTHING);
- }
- }, BackpressureStrategy.LATEST);
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava3 does not like null.
- *
- */
- @NonNull
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Flowable<T> createFlowable(@NonNull final RoomDatabase database,
- final boolean inTransaction, @NonNull final String[] tableNames,
- @NonNull final Callable<T> callable) {
- Scheduler scheduler = Schedulers.from(getExecutor(database, inTransaction));
- final Maybe<T> maybe = Maybe.fromCallable(callable);
- return createFlowable(database, tableNames)
- .subscribeOn(scheduler)
- .unsubscribeOn(scheduler)
- .observeOn(scheduler)
- .flatMapMaybe((Function<Object, MaybeSource<T>>) o -> maybe);
- }
-
- /**
- * Creates a {@link Observable} that emits at least once and also re-emits whenever one of the
- * observed tables is updated.
- * <p>
- * You can easily chain a database operation to downstream of this {@link Observable} to ensure
- * that it re-runs when database is modified.
- * <p>
- * Since database invalidation is batched, multiple changes in the database may results in just
- * 1 emission.
- *
- * @param database The database instance
- * @param tableNames The list of table names that should be observed
- * @return A {@link Observable} which emits {@link #NOTHING} when one of the observed tables
- * is modified (also once when the invalidation tracker connection is established).
- */
- @NonNull
- public static Observable<Object> createObservable(@NonNull final RoomDatabase database,
- @NonNull final String... tableNames) {
- return Observable.create(emitter -> {
- final InvalidationTracker.Observer observer = new InvalidationTracker.Observer(
- tableNames) {
- @Override
- public void onInvalidated(@androidx.annotation.NonNull Set<String> tables) {
- emitter.onNext(NOTHING);
- }
- };
- database.getInvalidationTracker().addObserver(observer);
- emitter.setDisposable(Disposable.fromAction(
- () -> database.getInvalidationTracker().removeObserver(observer)));
-
- // emit once to avoid missing any data and also easy chaining
- emitter.onNext(NOTHING);
- });
- }
-
- /**
- * Helper method used by generated code to bind a Callable such that it will be run in
- * our disk io thread and will automatically block null values since RxJava3 does not like null.
- *
- */
- @NonNull
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Observable<T> createObservable(@NonNull final RoomDatabase database,
- final boolean inTransaction, @NonNull final String[] tableNames,
- @NonNull final Callable<T> callable) {
- Scheduler scheduler = Schedulers.from(getExecutor(database, inTransaction));
- final Maybe<T> maybe = Maybe.fromCallable(callable);
- return createObservable(database, tableNames)
- .subscribeOn(scheduler)
- .unsubscribeOn(scheduler)
- .observeOn(scheduler)
- .flatMapMaybe(o -> maybe);
- }
-
- /**
- * Helper method used by generated code to create a Single from a Callable that will ignore
- * the EmptyResultSetException if the stream is already disposed.
- *
- */
- @NonNull
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- public static <T> Single<T> createSingle(@NonNull final Callable<? extends T> callable) {
- return Single.create(emitter -> {
- try {
- emitter.onSuccess(callable.call());
- } catch (EmptyResultSetException e) {
- emitter.tryOnError(e);
- }
- });
- }
-
- private static Executor getExecutor(@NonNull RoomDatabase database, boolean inTransaction) {
- if (inTransaction) {
- return database.getTransactionExecutor();
- } else {
- return database.getQueryExecutor();
- }
- }
-
- private RxRoom() {
- }
-}
diff --git a/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt
new file mode 100644
index 0000000..82ee4b5
--- /dev/null
+++ b/room/room-rxjava3/src/main/java/androidx/room/rxjava3/RxRoom.kt
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2020 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.
+ */
+@file:JvmName("RxRoom")
+
+package androidx.room.rxjava3
+
+import androidx.annotation.RestrictTo
+import androidx.room.InvalidationTracker
+import androidx.room.RoomDatabase
+import androidx.room.coroutines.createFlow
+import androidx.room.util.performBlocking
+import androidx.sqlite.SQLiteConnection
+import io.reactivex.rxjava3.core.BackpressureStrategy
+import io.reactivex.rxjava3.core.Completable
+import io.reactivex.rxjava3.core.Flowable
+import io.reactivex.rxjava3.core.FlowableEmitter
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.core.ObservableEmitter
+import io.reactivex.rxjava3.core.Single
+import io.reactivex.rxjava3.disposables.Disposable
+import io.reactivex.rxjava3.schedulers.Schedulers
+import java.util.concurrent.Callable
+import java.util.concurrent.Executor
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.rx3.asObservable
+
+/** Marker class used by annotation processor to identify dependency is in the classpath. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) class Rx3RoomArtifactMarker private constructor()
+
+/** Data dispatched by the publisher created by [createFlowable]. */
+@JvmField val NOTHING: Any = Any()
+
+/** Helper function used by generated code to create a [Flowable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createFlowable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Flowable<T> =
+ createObservable(db, inTransaction, tableNames, block).toFlowable(BackpressureStrategy.LATEST)
+
+/** Helper function used by generated code to create a [Observable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createObservable(
+ db: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ block: (SQLiteConnection) -> T?
+): Observable<T> =
+ createFlow(db, inTransaction, tableNames, block)
+ .filterNotNull()
+ .asObservable(db.getQueryContext())
+
+/** Helper function used by generated code to create a [Maybe] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createMaybe(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Maybe<T> =
+ Maybe.fromCallable(Callable<T> { performBlocking(db, isReadOnly, inTransaction, block) })
+
+/** Helper function used by generated code to create a [Completable] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun createCompletable(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> Unit
+): Completable = Completable.fromCallable { performBlocking(db, isReadOnly, inTransaction, block) }
+
+/** Helper function used by generated code to create a [Single] */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createSingle(
+ db: RoomDatabase,
+ isReadOnly: Boolean,
+ inTransaction: Boolean,
+ block: (SQLiteConnection) -> T?
+): Single<T> =
+ Single.create { emitter ->
+ if (emitter.isDisposed) return@create
+ try {
+ val result = performBlocking(db, isReadOnly, inTransaction, block)
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+
+/**
+ * Creates a [Flowable] that emits at least once and also re-emits whenever one of the observed
+ * tables is updated.
+ *
+ * You can easily chain a database operation to downstream of this [Flowable] to ensure that it
+ * re-runs when database is modified.
+ *
+ * Since database invalidation is batched, multiple changes in the database may results in just 1
+ * emission.
+ *
+ * @param database The database instance
+ * @param tableNames The list of table names that should be observed
+ * @return A [Flowable] which emits [NOTHING] when one of the observed tables is modified (also once
+ * when the invalidation tracker connection is established).
+ */
+fun createFlowable(database: RoomDatabase, vararg tableNames: String): Flowable<Any> {
+ return Flowable.create(
+ { emitter: FlowableEmitter<Any> ->
+ val observer =
+ object : InvalidationTracker.Observer(tableNames) {
+ override fun onInvalidated(tables: Set<String>) {
+ if (!emitter.isCancelled) {
+ emitter.onNext(NOTHING)
+ }
+ }
+ }
+ if (!emitter.isCancelled) {
+ database.invalidationTracker.addObserver(observer)
+ emitter.setDisposable(
+ Disposable.fromAction { database.invalidationTracker.removeObserver(observer) }
+ )
+ }
+
+ // emit once to avoid missing any data and also easy chaining
+ if (!emitter.isCancelled) {
+ emitter.onNext(NOTHING)
+ }
+ },
+ BackpressureStrategy.LATEST
+ )
+}
+
+/**
+ * Helper method used by generated code to bind a Callable such that it will be run in our disk io
+ * thread and will automatically block null values since RxJava3 does not like null.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@Deprecated("No longer used by generated code.")
+fun <T : Any> createFlowable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Flowable<T> {
+ val scheduler = Schedulers.from(getExecutor(database, inTransaction))
+ val maybe = Maybe.fromCallable(callable)
+ return createFlowable(database, *tableNames)
+ .subscribeOn(scheduler)
+ .unsubscribeOn(scheduler)
+ .observeOn(scheduler)
+ .flatMapMaybe { maybe }
+}
+
+/**
+ * Creates a [Observable] that emits at least once and also re-emits whenever one of the observed
+ * tables is updated.
+ *
+ * You can easily chain a database operation to downstream of this [Observable] to ensure that it
+ * re-runs when database is modified.
+ *
+ * Since database invalidation is batched, multiple changes in the database may results in just 1
+ * emission.
+ *
+ * @param database The database instance
+ * @param tableNames The list of table names that should be observed
+ * @return A [Observable] which emits [NOTHING] when one of the observed tables is modified (also
+ * once when the invalidation tracker connection is established).
+ */
+fun createObservable(database: RoomDatabase, vararg tableNames: String): Observable<Any> {
+ return Observable.create { emitter: ObservableEmitter<Any> ->
+ val observer =
+ object : InvalidationTracker.Observer(tableNames) {
+ override fun onInvalidated(tables: Set<String>) {
+ emitter.onNext(NOTHING)
+ }
+ }
+ database.invalidationTracker.addObserver(observer)
+ emitter.setDisposable(
+ Disposable.fromAction { database.invalidationTracker.removeObserver(observer) }
+ )
+
+ // emit once to avoid missing any data and also easy chaining
+ emitter.onNext(NOTHING)
+ }
+}
+
+/**
+ * Helper method used by generated code to bind a Callable such that it will be run in our disk io
+ * thread and will automatically block null values since RxJava3 does not like null.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+@Deprecated("No longer used by generated code.")
+fun <T : Any> createObservable(
+ database: RoomDatabase,
+ inTransaction: Boolean,
+ tableNames: Array<String>,
+ callable: Callable<out T>
+): Observable<T> {
+ val scheduler = Schedulers.from(getExecutor(database, inTransaction))
+ val maybe = Maybe.fromCallable(callable)
+ return createObservable(database, *tableNames)
+ .subscribeOn(scheduler)
+ .unsubscribeOn(scheduler)
+ .observeOn(scheduler)
+ .flatMapMaybe { maybe }
+}
+
+/**
+ * Helper method used by generated code to create a Single from a Callable that will ignore the
+ * EmptyResultSetException if the stream is already disposed.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+fun <T : Any> createSingle(callable: Callable<out T>): Single<T> {
+ return Single.create { emitter ->
+ try {
+ val result = callable.call()
+ if (result != null) {
+ emitter.onSuccess(result)
+ } else {
+ throw EmptyResultSetException("Query returned empty result set.")
+ }
+ } catch (e: EmptyResultSetException) {
+ emitter.tryOnError(e)
+ }
+ }
+}
+
+private fun getExecutor(database: RoomDatabase, inTransaction: Boolean): Executor {
+ return if (inTransaction) {
+ database.transactionExecutor
+ } else {
+ database.queryExecutor
+ }
+}
diff --git a/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt b/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
index 256e5c2..27f5606 100644
--- a/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
+++ b/room/room-rxjava3/src/test/java/androidx/room/rxjava3/RxRoomTest.kt
@@ -23,6 +23,7 @@
import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.observers.TestObserver
import io.reactivex.rxjava3.subscribers.TestSubscriber
+import java.util.concurrent.Callable
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import org.junit.Before
@@ -62,7 +63,7 @@
@Test
fun basicAddRemove_Flowable() {
- val flowable = RxRoom.createFlowable(mDatabase, "a", "b")
+ val flowable = createFlowable(mDatabase, "a", "b")
verify(mInvalidationTracker, never()).addObserver(any())
var disposable = flowable.subscribe()
verify(mInvalidationTracker).addObserver(any())
@@ -82,7 +83,7 @@
@Test
fun basicAddRemove_Observable() {
- val observable = RxRoom.createObservable(mDatabase, "a", "b")
+ val observable = createObservable(mDatabase, "a", "b")
verify(mInvalidationTracker, never()).addObserver(any())
var disposable = observable.subscribe()
verify(mInvalidationTracker).addObserver(any())
@@ -104,7 +105,7 @@
fun basicNotify_Flowable() {
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, *tables)
+ val flowable = createFlowable(mDatabase, *tables)
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
assertThat(mAddedObservers.size).isEqualTo(1)
@@ -123,7 +124,7 @@
fun basicNotify_Observable() {
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val observable = RxRoom.createObservable(mDatabase, *tables)
+ val observable = createObservable(mDatabase, *tables)
val consumer = CountingConsumer()
val disposable = observable.subscribe(consumer)
assertThat(mAddedObservers.size).isEqualTo(1)
@@ -139,12 +140,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Flowable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createFlowable(mDatabase, false, tables) { value.get() }
+ val flowable = createFlowable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
drain()
@@ -169,12 +170,12 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun internalCallable_Observable() {
val value = AtomicReference<Any>(null)
val tables = arrayOf("a", "b")
val tableSet: Set<String> = HashSet(listOf(*tables))
- val flowable = RxRoom.createObservable(mDatabase, false, tables) { value.get() }
+ val flowable = createObservable(mDatabase, false, tables, Callable { value.get() })
val consumer = CountingConsumer()
val disposable = flowable.subscribe(consumer)
drain()
@@ -199,12 +200,15 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun exception_Flowable() {
val flowable =
- RxRoom.createFlowable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ createFlowable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val subscriber = TestSubscriber<String>()
flowable.subscribe(subscriber)
drain()
@@ -212,12 +216,15 @@
}
@Test
- @Throws(Exception::class)
+ @Suppress("DEPRECATION")
fun exception_Observable() {
val flowable =
- RxRoom.createObservable<String>(mDatabase, false, arrayOf("a")) {
- throw Exception("i want exception")
- }
+ createObservable<String>(
+ mDatabase,
+ false,
+ arrayOf("a"),
+ Callable { throw Exception("i want exception") }
+ )
val observer = TestObserver<String>()
flowable.subscribe(observer)
drain()
diff --git a/sqlite/sqlite-bundled/build.gradle b/sqlite/sqlite-bundled/build.gradle
index 6c4caeb..3bc7daf 100644
--- a/sqlite/sqlite-bundled/build.gradle
+++ b/sqlite/sqlite-bundled/build.gradle
@@ -249,5 +249,4 @@
inceptionYear = "2023"
description = "The implementation of SQLite library using the bundled SQLite."
metalavaK2UastEnabled = false
- legacyDisableKotlinStrictApiMode = true
}
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
index 6adf9ca..30bd8d1 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
@@ -23,39 +23,39 @@
import kotlin.jvm.JvmName
/** Opens the database in read-only mode. */
-const val SQLITE_OPEN_READONLY = 0x00000001
+public const val SQLITE_OPEN_READONLY: Int = 0x00000001
/** Opens the database for reading and writing. */
-const val SQLITE_OPEN_READWRITE = 0x00000002
+public const val SQLITE_OPEN_READWRITE: Int = 0x00000002
/** Create the database if it does not already exist. */
-const val SQLITE_OPEN_CREATE = 0x00000004
+public const val SQLITE_OPEN_CREATE: Int = 0x00000004
/** Interpret the filename as a URI. */
-const val SQLITE_OPEN_URI = 0x00000040
+public const val SQLITE_OPEN_URI: Int = 0x00000040
/** Opens the database as a in-memory database. */
-const val SQLITE_OPEN_MEMORY = 0x00000080
+public const val SQLITE_OPEN_MEMORY: Int = 0x00000080
/**
* The database connection will use the "multi-thread" threading mode.
*
* See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
*/
-const val SQLITE_OPEN_NOMUTEX = 0x00008000
+public const val SQLITE_OPEN_NOMUTEX: Int = 0x00008000
/**
* The database connection will use the "serialized" threading mode.
*
* See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
*/
-const val SQLITE_OPEN_FULLMUTEX = 0x00010000
+public const val SQLITE_OPEN_FULLMUTEX: Int = 0x00010000
/** The filename is not allowed to contain a symbolic link. */
-const val SQLITE_OPEN_NOFOLLOW = 0x01000000
+public const val SQLITE_OPEN_NOFOLLOW: Int = 0x01000000
/** The database connection will use extended result codes. */
-const val SQLITE_OPEN_EXRESCODE = 0x02000000
+public const val SQLITE_OPEN_EXRESCODE: Int = 0x02000000
/** The flags constant that can be used with [BundledSQLiteDriver.open]. */
@IntDef(
@@ -75,4 +75,4 @@
)
@Retention(AnnotationRetention.SOURCE)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-expect annotation class OpenFlag()
+public expect annotation class OpenFlag()
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.kt
index 49b5731..0eec41a 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.kt
@@ -20,4 +20,5 @@
import androidx.sqlite.SQLiteConnection
// Restricted instead of internal due to KT-37316
-@RestrictTo(RestrictTo.Scope.LIBRARY) expect class BundledSQLiteConnection : SQLiteConnection
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public expect class BundledSQLiteConnection : SQLiteConnection
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
index b55c476..66ee02b 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
@@ -24,14 +24,14 @@
* A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of this
* library.
*/
-expect class BundledSQLiteDriver() : SQLiteDriver {
+public expect class BundledSQLiteDriver() : SQLiteDriver {
/**
* The thread safe mode SQLite was compiled with.
*
* See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) val threadingMode: Int
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public val threadingMode: Int
/**
* Opens a new database connection.
@@ -42,5 +42,5 @@
* @param flags Connection open flags.
* @return the database connection.
*/
- fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection
+ public fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection
}
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.kt
index a48d56e..7b82a28 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.kt
@@ -20,4 +20,4 @@
import androidx.sqlite.SQLiteStatement
// Restricted instead of internal due to KT-37316
-@RestrictTo(RestrictTo.Scope.LIBRARY) expect class BundledSQLiteStatement : SQLiteStatement
+@RestrictTo(RestrictTo.Scope.LIBRARY) public expect class BundledSQLiteStatement : SQLiteStatement
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
index 1717770..d283118 100644
--- a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
@@ -36,7 +36,7 @@
)
@Retention(AnnotationRetention.SOURCE)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-actual annotation class OpenFlag
+public actual annotation class OpenFlag
internal object ResultCode {
const val SQLITE_MISUSE = 21
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
index 65be6da..3d34667 100644
--- a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
@@ -24,7 +24,8 @@
import androidx.sqlite.throwSQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-actual class BundledSQLiteConnection(private val connectionPointer: Long) : SQLiteConnection {
+public actual class BundledSQLiteConnection(private val connectionPointer: Long) :
+ SQLiteConnection {
@OptIn(ExperimentalStdlibApi::class) @Volatile private var isClosed = false
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
index de1e6eb..a38a069 100644
--- a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
@@ -27,7 +27,7 @@
*/
// TODO(b/313895287): Explore usability of @FastNative and @CriticalNative for the external
// functions.
-actual class BundledSQLiteDriver : SQLiteDriver {
+public actual class BundledSQLiteDriver : SQLiteDriver {
/**
* The thread safe mode SQLite was compiled with.
@@ -35,7 +35,7 @@
* See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
*/
@get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- actual val threadingMode: Int
+ public actual val threadingMode: Int
get() = nativeThreadSafeMode()
override fun open(fileName: String): SQLiteConnection {
@@ -51,7 +51,7 @@
* @param flags Connection open flags.
* @return the database connection.
*/
- actual fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection {
+ public actual fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection {
val address = nativeOpen(fileName, flags)
return BundledSQLiteConnection(address)
}
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
index f33c4ab..f2577c5 100644
--- a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
@@ -23,7 +23,7 @@
import androidx.sqlite.throwSQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-actual class BundledSQLiteStatement(
+public actual class BundledSQLiteStatement(
private val connectionPointer: Long,
private val statementPointer: Long
) : SQLiteStatement {
@@ -118,7 +118,7 @@
}
}
- companion object {
+ private companion object {
private const val COLUMN_TYPE_INTEGER = 1
private const val COLUMN_TYPE_FLOAT = 2
private const val COLUMN_TYPE_TEXT = 3
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
index d3d1d5d..2a65818 100644
--- a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
@@ -16,4 +16,4 @@
package androidx.sqlite.driver.bundled
-actual typealias OpenFlag = androidx.sqlite.driver.OpenFlag
+public actual typealias OpenFlag = androidx.sqlite.driver.OpenFlag
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
index d466e1a..a368590 100644
--- a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
@@ -20,4 +20,4 @@
import androidx.annotation.RestrictTo
-actual typealias BundledSQLiteConnection = androidx.sqlite.driver.NativeSQLiteConnection
+public actual typealias BundledSQLiteConnection = androidx.sqlite.driver.NativeSQLiteConnection
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
index c39d148..4d2be0d 100644
--- a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
@@ -22,4 +22,4 @@
* A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of this
* library.
*/
-actual typealias BundledSQLiteDriver = androidx.sqlite.driver.NativeSQLiteDriver
+public actual typealias BundledSQLiteDriver = androidx.sqlite.driver.NativeSQLiteDriver
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
index 92e09eb..7afcd68 100644
--- a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
@@ -20,4 +20,4 @@
import androidx.annotation.RestrictTo
-actual typealias BundledSQLiteStatement = androidx.sqlite.driver.NativeSQLiteStatement
+public actual typealias BundledSQLiteStatement = androidx.sqlite.driver.NativeSQLiteStatement
diff --git a/sqlite/sqlite-framework/build.gradle b/sqlite/sqlite-framework/build.gradle
index 7ad2380..411b332f 100644
--- a/sqlite/sqlite-framework/build.gradle
+++ b/sqlite/sqlite-framework/build.gradle
@@ -146,7 +146,6 @@
type = LibraryType.PUBLISHED_LIBRARY
inceptionYear = "2017"
description = "The implementation of SQLite library using the framework code."
- legacyDisableKotlinStrictApiMode = true
}
android {
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.android.kt
index f4a55ee..fc1617e 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/db/framework/FrameworkSQLiteOpenHelperFactory.android.kt
@@ -20,7 +20,7 @@
/**
* Implements [SupportSQLiteOpenHelper.Factory] using the SQLite implementation in the framework.
*/
-class FrameworkSQLiteOpenHelperFactory : SupportSQLiteOpenHelper.Factory {
+public class FrameworkSQLiteOpenHelperFactory : SupportSQLiteOpenHelper.Factory {
override fun create(
configuration: SupportSQLiteOpenHelper.Configuration
): SupportSQLiteOpenHelper {
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
index 375a279..75ae53e 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteConnection.android.kt
@@ -24,7 +24,7 @@
import androidx.sqlite.throwSQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-class AndroidSQLiteConnection(val db: SQLiteDatabase) : SQLiteConnection {
+public class AndroidSQLiteConnection(public val db: SQLiteDatabase) : SQLiteConnection {
override fun prepare(sql: String): SQLiteStatement {
if (db.isOpen) {
return AndroidSQLiteStatement.create(db, sql)
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteDriver.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteDriver.android.kt
index 245be46..9db9d96 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteDriver.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/driver/AndroidSQLiteDriver.android.kt
@@ -23,7 +23,7 @@
/**
* A [SQLiteDriver] implemented by [android.database] and that uses the Android's SDK SQLite APIs.
*/
-class AndroidSQLiteDriver : SQLiteDriver {
+public class AndroidSQLiteDriver : SQLiteDriver {
override fun open(fileName: String): SQLiteConnection {
val database = SQLiteDatabase.openOrCreateDatabase(fileName, null)
return AndroidSQLiteConnection(database)
diff --git a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/util/ProcessLock.android.kt b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/util/ProcessLock.android.kt
index ebb9046..706903c 100644
--- a/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/util/ProcessLock.android.kt
+++ b/sqlite/sqlite-framework/src/androidMain/kotlin/androidx/sqlite/util/ProcessLock.android.kt
@@ -47,7 +47,7 @@
* can be overridden via the [lock] method.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class ProcessLock(name: String, lockDir: File?, private val processLock: Boolean) {
+public class ProcessLock(name: String, lockDir: File?, private val processLock: Boolean) {
private val lockFile: File? = lockDir?.let { File(it, "$name.lck") }
private val threadLock: Lock = getThreadLock(name)
private var lockChannel: FileChannel? = null
@@ -57,7 +57,7 @@
*
* @param [processLock] whether to use file for process level locking or not.
*/
- fun lock(processLock: Boolean = this.processLock) {
+ public fun lock(processLock: Boolean = this.processLock) {
threadLock.lock()
if (processLock) {
try {
@@ -76,14 +76,14 @@
}
/** Releases the lock. */
- fun unlock() {
+ public fun unlock() {
try {
lockChannel?.close()
} catch (ignored: IOException) {}
threadLock.unlock()
}
- companion object {
+ private companion object {
private const val TAG = "SupportSQLiteLock"
// in-process lock map
private val threadLocksMap: MutableMap<String, Lock> = HashMap()
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
index 0e060fa..2534593 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
@@ -52,7 +52,7 @@
)
@Retention(AnnotationRetention.SOURCE)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-annotation class OpenFlag
+public annotation class OpenFlag
internal fun CPointer<sqlite3>.getErrorMsg(): String? {
return sqlite3_errmsg16(this)?.reinterpret<UShortVar>()?.toKStringFromUtf16()
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteConnection.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteConnection.kt
index c3fce96..6ff1dbb 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteConnection.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteConnection.kt
@@ -35,7 +35,7 @@
import sqlite3.sqlite3_prepare16_v2
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) // For actual typealias in unbundled
-class NativeSQLiteConnection(private val dbPointer: CPointer<sqlite3>) : SQLiteConnection {
+public class NativeSQLiteConnection(private val dbPointer: CPointer<sqlite3>) : SQLiteConnection {
@OptIn(ExperimentalStdlibApi::class) @Volatile private var isClosed = false
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
index 5040a1e..ebfe6d8 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
@@ -36,7 +36,7 @@
*
* Usage of this driver expects that `libsqlite` can be found in the shared library path.
*/
-class NativeSQLiteDriver : SQLiteDriver {
+public class NativeSQLiteDriver : SQLiteDriver {
/**
* The thread safe mode SQLite was compiled with.
@@ -44,7 +44,7 @@
* See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
*/
@get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
- val threadingMode: Int
+ public val threadingMode: Int
get() = sqlite3_threadsafe()
override fun open(fileName: String): SQLiteConnection {
@@ -60,7 +60,7 @@
* @param flags Connection open flags.
* @return the database connection.
*/
- fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection = memScoped {
+ public fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection = memScoped {
val dbPointer = allocPointerTo<sqlite3>()
val resultCode =
sqlite3_open_v2(filename = fileName, ppDb = dbPointer.ptr, flags = flags, zVfs = null)
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteStatement.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteStatement.kt
index 1995de0..dfd2829 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteStatement.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteStatement.kt
@@ -57,7 +57,7 @@
import sqlite3.sqlite3_step
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) // For actual typealias in unbundled
-class NativeSQLiteStatement(
+public class NativeSQLiteStatement(
private val dbPointer: CPointer<sqlite3>,
private val stmtPointer: CPointer<sqlite3_stmt>
) : SQLiteStatement {
diff --git a/sqlite/sqlite-ktx/build.gradle b/sqlite/sqlite-ktx/build.gradle
index b03f306..90d69c5 100644
--- a/sqlite/sqlite-ktx/build.gradle
+++ b/sqlite/sqlite-ktx/build.gradle
@@ -42,7 +42,6 @@
type = LibraryType.PUBLISHED_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS
inceptionYear = "2018"
description = "Kotlin extensions for DB"
- legacyDisableKotlinStrictApiMode = true
}
android {
diff --git a/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt b/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
index e637a991..51d244f 100644
--- a/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
+++ b/sqlite/sqlite-ktx/src/main/java/androidx/sqlite/db/SupportSQLiteDatabaseExt.kt
@@ -23,7 +23,7 @@
* @param exclusive Run in `EXCLUSIVE` mode when true, `IMMEDIATE` mode otherwise.
* @param body Lambda to be run in the transaction.
*/
-inline fun <T> SupportSQLiteDatabase.transaction(
+public inline fun <T> SupportSQLiteDatabase.transaction(
exclusive: Boolean = true,
body: SupportSQLiteDatabase.() -> T
): T {
diff --git a/sqlite/sqlite/build.gradle b/sqlite/sqlite/build.gradle
index 59c4baf..3c4a438 100644
--- a/sqlite/sqlite/build.gradle
+++ b/sqlite/sqlite/build.gradle
@@ -90,5 +90,4 @@
type = LibraryType.PUBLISHED_LIBRARY
inceptionYear = "2017"
description = "SQLite API"
- legacyDisableKotlinStrictApiMode = true
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/SQLiteException.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/SQLiteException.android.kt
index febb4af..6401e1f 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/SQLiteException.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/SQLiteException.android.kt
@@ -15,4 +15,4 @@
*/
package androidx.sqlite
-actual typealias SQLiteException = android.database.SQLException
+public actual typealias SQLiteException = android.database.SQLException
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
index bbe86d9..1939a45 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SimpleSQLiteQuery.android.kt
@@ -24,7 +24,7 @@
* @constructor Creates an SQL query with the sql string and the bind arguments.
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-class SimpleSQLiteQuery(
+public class SimpleSQLiteQuery(
private val query: String,
@Suppress("ArrayReturn") // Due to legacy API
private val bindArgs: Array<out Any?>?
@@ -35,7 +35,7 @@
*
* @param query The SQL query to execute. Cannot include bind parameters.
*/
- constructor(query: String) : this(query, null)
+ public constructor(query: String) : this(query, null)
override val sql: String
get() = this.query
@@ -53,7 +53,7 @@
override val argCount: Int
get() = bindArgs?.size ?: 0
- companion object {
+ public companion object {
/**
* Binds the given arguments into the given sqlite statement.
*
@@ -61,7 +61,7 @@
* @param [bindArgs] The list of bind arguments
*/
@JvmStatic
- fun bind(
+ public fun bind(
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
statement: SupportSQLiteProgram,
@Suppress("ArrayReturn") // Due to legacy API
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteCompat.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteCompat.android.kt
index 856d8ba..8e56dc1 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteCompat.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteCompat.android.kt
@@ -26,11 +26,11 @@
/** Helper for accessing features in [SupportSQLiteOpenHelper]. */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class SupportSQLiteCompat private constructor() {
+public class SupportSQLiteCompat private constructor() {
/** Helper for accessing functions that require SDK version 21 and higher. */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@RequiresApi(21)
- object Api21Impl {
+ public object Api21Impl {
/**
* Returns the absolute path to the directory on the filesystem.
*
@@ -39,7 +39,7 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@JvmStatic
- fun getNoBackupFilesDir(context: Context): File {
+ public fun getNoBackupFilesDir(context: Context): File {
return context.noBackupFilesDir
}
}
@@ -47,7 +47,7 @@
/** Helper for accessing functions that require SDK version 23 and higher. */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@RequiresApi(23)
- object Api23Impl {
+ public object Api23Impl {
/**
* Sets a [Bundle] that will be returned by [Cursor.getExtras].
*
@@ -55,7 +55,7 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@JvmStatic
- fun setExtras(cursor: Cursor, extras: Bundle) {
+ public fun setExtras(cursor: Cursor, extras: Bundle) {
cursor.extras = extras
}
}
@@ -63,7 +63,7 @@
/** Helper for accessing functions that require SDK version 29 and higher. */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@RequiresApi(29)
- object Api29Impl {
+ public object Api29Impl {
/**
* Similar to [Cursor.setNotificationUri], except this version allows to watch multiple
* content URIs for changes.
@@ -74,7 +74,7 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@JvmStatic
- fun setNotificationUris(cursor: Cursor, cr: ContentResolver, uris: List<Uri?>) {
+ public fun setNotificationUris(cursor: Cursor, cr: ContentResolver, uris: List<Uri?>) {
cursor.setNotificationUris(cr, uris)
}
@@ -88,7 +88,7 @@
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@JvmStatic
- fun getNotificationUris(cursor: Cursor): List<Uri> {
+ public fun getNotificationUris(cursor: Cursor): List<Uri> {
return cursor.notificationUris!!
}
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
index 4f4e98c..5c6d9dd 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteDatabase.android.kt
@@ -30,14 +30,14 @@
* versions. It mimics the behavior of [android.database.sqlite.SQLiteDatabase]
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SupportSQLiteDatabase : Closeable {
+public interface SupportSQLiteDatabase : Closeable {
/**
* Compiles the given SQL statement.
*
* @param sql The sql query.
* @return Compiled statement.
*/
- fun compileStatement(sql: String): SupportSQLiteStatement
+ public fun compileStatement(sql: String): SupportSQLiteStatement
/**
* Begins a transaction in EXCLUSIVE mode.
@@ -58,7 +58,7 @@
* }
* ```
*/
- fun beginTransaction()
+ public fun beginTransaction()
/**
* Begins a transaction in IMMEDIATE mode. Transactions can be nested. When the outer
@@ -78,7 +78,7 @@
* }
* ```
*/
- fun beginTransactionNonExclusive()
+ public fun beginTransactionNonExclusive()
/**
* Begins a transaction in DEFERRED mode, with the android-specific constraint that the
@@ -107,7 +107,7 @@
* If the implementation does not support read-only transactions then the default implementation
* delegates to [beginTransaction].
*/
- fun beginTransactionReadOnly() {
+ public fun beginTransactionReadOnly() {
beginTransaction()
}
@@ -133,7 +133,7 @@
* @param transactionListener listener that should be notified when the transaction begins,
* commits, or is rolled back, either explicitly or by a call to [yieldIfContendedSafely].
*/
- fun beginTransactionWithListener(transactionListener: SQLiteTransactionListener)
+ public fun beginTransactionWithListener(transactionListener: SQLiteTransactionListener)
/**
* Begins a transaction in IMMEDIATE mode. Transactions can be nested. When the outer
@@ -156,7 +156,9 @@
* @param transactionListener listener that should be notified when the transaction begins,
* commits, or is rolled back, either explicitly or by a call to [yieldIfContendedSafely].
*/
- fun beginTransactionWithListenerNonExclusive(transactionListener: SQLiteTransactionListener)
+ public fun beginTransactionWithListenerNonExclusive(
+ transactionListener: SQLiteTransactionListener
+ )
/**
* Begins a transaction in read-only mode with a {@link SQLiteTransactionListener} listener. The
@@ -182,7 +184,9 @@
* delegates to [beginTransactionWithListener].
*/
@Suppress("ExecutorRegistration")
- fun beginTransactionWithListenerReadOnly(transactionListener: SQLiteTransactionListener) {
+ public fun beginTransactionWithListenerReadOnly(
+ transactionListener: SQLiteTransactionListener
+ ) {
beginTransactionWithListener(transactionListener)
}
@@ -190,7 +194,7 @@
* End a transaction. See beginTransaction for notes about how to use this and when transactions
* are committed and rolled back.
*/
- fun endTransaction()
+ public fun endTransaction()
/**
* Marks the current transaction as successful. Do not do any more database work between calling
@@ -201,14 +205,14 @@
* @throws IllegalStateException if the current thread is not in a transaction or the
* transaction is already marked as successful.
*/
- fun setTransactionSuccessful()
+ public fun setTransactionSuccessful()
/**
* Returns true if the current thread has a transaction pending.
*
* @return True if the current thread is in a transaction.
*/
- fun inTransaction(): Boolean
+ public fun inTransaction(): Boolean
/**
* True if the current thread is holding an active connection to the database.
@@ -218,7 +222,7 @@
* longer a true "database lock" although threads may block if they cannot acquire a database
* connection to perform a particular operation.
*/
- val isDbLockedByCurrentThread: Boolean
+ public val isDbLockedByCurrentThread: Boolean
/**
* Temporarily end the transaction to let other threads run. The transaction is assumed to be
@@ -229,7 +233,7 @@
*
* @return true if the transaction was yielded
*/
- fun yieldIfContendedSafely(): Boolean
+ public fun yieldIfContendedSafely(): Boolean
/**
* Temporarily end the transaction to let other threads run. The transaction is assumed to be
@@ -243,11 +247,11 @@
* more progress than they would if we started the transaction immediately.
* @return true if the transaction was yielded
*/
- fun yieldIfContendedSafely(sleepAfterYieldDelayMillis: Long): Boolean
+ public fun yieldIfContendedSafely(sleepAfterYieldDelayMillis: Long): Boolean
/** Is true if [execPerConnectionSQL] is supported by the implementation. */
@get:Suppress("AcronymName") // To keep consistency with framework method name.
- val isExecPerConnectionSQLSupported: Boolean
+ public val isExecPerConnectionSQLSupported: Boolean
get() = false
/**
@@ -272,15 +276,18 @@
* supported use [isExecPerConnectionSQLSupported]
*/
@Suppress("AcronymName") // To keep consistency with framework method name.
- fun execPerConnectionSQL(sql: String, @SuppressLint("ArrayReturn") bindArgs: Array<out Any?>?) {
+ public fun execPerConnectionSQL(
+ sql: String,
+ @SuppressLint("ArrayReturn") bindArgs: Array<out Any?>?
+ ) {
throw UnsupportedOperationException()
}
/** The database version. */
- var version: Int
+ public var version: Int
/** The maximum size the database may grow to. */
- val maximumSize: Long
+ public val maximumSize: Long
/**
* Sets the maximum size the database will grow to. The maximum size cannot be set below the
@@ -289,7 +296,7 @@
* @param numBytes the maximum database size, in bytes
* @return the new maximum database size
*/
- fun setMaximumSize(numBytes: Long): Long
+ public fun setMaximumSize(numBytes: Long): Long
/**
* The current database page size, in bytes.
@@ -297,7 +304,7 @@
* The page size must be a power of two. This method does not work if any data has been written
* to the database file, and must be called right after the database has been created.
*/
- var pageSize: Long
+ public var pageSize: Long
/**
* Runs the given query on the database. If you would like to have typed bind arguments, use
@@ -308,7 +315,7 @@
* @return A [Cursor] object, which is positioned before the first entry. Note that [Cursor]s
* are not synchronized, see the documentation for more details.
*/
- fun query(query: String): Cursor
+ public fun query(query: String): Cursor
/**
* Runs the given query on the database. If you would like to have bind arguments, use [query].
@@ -319,7 +326,7 @@
* @return A [Cursor] object, which is positioned before the first entry. Note that [Cursor]s
* are not synchronized, see the documentation for more details.
*/
- fun query(query: String, bindArgs: Array<out Any?>): Cursor
+ public fun query(query: String, bindArgs: Array<out Any?>): Cursor
/**
* Runs the given query on the database.
@@ -331,7 +338,7 @@
* @return A [Cursor] object, which is positioned before the first entry. Note that [Cursor]s
* are not synchronized, see the documentation for more details.
*/
- fun query(query: SupportSQLiteQuery): Cursor
+ public fun query(query: SupportSQLiteQuery): Cursor
/**
* Runs the given query on the database.
@@ -346,7 +353,7 @@
* @return A [Cursor] object, which is positioned before the first entry. Note that [Cursor]s
* are not synchronized, see the documentation for more details.
*/
- fun query(query: SupportSQLiteQuery, cancellationSignal: CancellationSignal?): Cursor
+ public fun query(query: SupportSQLiteQuery, cancellationSignal: CancellationSignal?): Cursor
/**
* Convenience method for inserting a row into the database.
@@ -365,7 +372,7 @@
* @throws SQLException If the insert fails
*/
@Throws(SQLException::class)
- fun insert(table: String, conflictAlgorithm: Int, values: ContentValues): Long
+ public fun insert(table: String, conflictAlgorithm: Int, values: ContentValues): Long
/**
* Convenience method for deleting rows in the database.
@@ -378,7 +385,7 @@
* @return the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all
* rows and get a count pass "1" as the whereClause.
*/
- fun delete(table: String, whereClause: String?, whereArgs: Array<out Any?>?): Int
+ public fun delete(table: String, whereClause: String?, whereArgs: Array<out Any?>?): Int
/**
* Convenience method for updating rows in the database.
@@ -399,7 +406,7 @@
* from whereArgs. The values will be bound as Strings.
* @return the number of rows affected
*/
- fun update(
+ public fun update(
table: String,
conflictAlgorithm: Int,
values: ContentValues,
@@ -420,7 +427,7 @@
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
@Throws(SQLException::class)
- fun execSQL(sql: String)
+ public fun execSQL(sql: String)
/**
* Execute a single SQL statement that does not return any data.
@@ -436,13 +443,13 @@
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
@Throws(SQLException::class)
- fun execSQL(sql: String, bindArgs: Array<out Any?>)
+ public fun execSQL(sql: String, bindArgs: Array<out Any?>)
/** Is true if the database is opened as read only. */
- val isReadOnly: Boolean
+ public val isReadOnly: Boolean
/** Is true if the database is currently open. */
- val isOpen: Boolean
+ public val isOpen: Boolean
/**
* Returns true if the new version code is greater than the current database version.
@@ -450,10 +457,10 @@
* @param newVersion The new version code.
* @return True if the new version code is greater than the current database version.
*/
- fun needUpgrade(newVersion: Int): Boolean
+ public fun needUpgrade(newVersion: Int): Boolean
/** The path to the database file. */
- val path: String?
+ public val path: String?
/**
* Sets the locale for this database. Does nothing if this database has the
@@ -465,7 +472,7 @@
* there is no collator available for the locale you requested. In this case the database
* remains unchanged.
*/
- fun setLocale(locale: Locale)
+ public fun setLocale(locale: Locale)
/**
* Sets the maximum size of the prepared-statement cache for this database. (size of the cache =
@@ -482,7 +489,7 @@
* @throws IllegalStateException if input cacheSize is over the max.
* [android.database.sqlite.SQLiteDatabase.MAX_SQL_CACHE_SIZE].
*/
- fun setMaxSqlCacheSize(cacheSize: Int)
+ public fun setMaxSqlCacheSize(cacheSize: Int)
/**
* Sets whether foreign key constraints are enabled for the database.
@@ -509,7 +516,7 @@
* @throws IllegalStateException if the are transactions is in progress when this method is
* called.
*/
- fun setForeignKeyConstraintsEnabled(enabled: Boolean)
+ public fun setForeignKeyConstraintsEnabled(enabled: Boolean)
/**
* This method enables parallel execution of queries from multiple threads on the same database.
@@ -573,7 +580,7 @@
* @throws IllegalStateException if there are transactions in progress at the time this method
* is called. WAL mode can only be changed when there are no transactions in progress.
*/
- fun enableWriteAheadLogging(): Boolean
+ public fun enableWriteAheadLogging(): Boolean
/**
* This method disables the features enabled by [enableWriteAheadLogging].
@@ -581,20 +588,20 @@
* @throws IllegalStateException if there are transactions in progress at the time this method
* is called. WAL mode can only be changed when there are no transactions in progress.
*/
- fun disableWriteAheadLogging()
+ public fun disableWriteAheadLogging()
/** Is true if write-ahead logging has been enabled for this database. */
- val isWriteAheadLoggingEnabled: Boolean
+ public val isWriteAheadLoggingEnabled: Boolean
/**
* The list of full path names of all attached databases including the main database by
* executing 'pragma database_list' on the database.
*/
- @get:Suppress("NullableCollection") val attachedDbs: List<Pair<String, String>>?
+ @get:Suppress("NullableCollection") public val attachedDbs: List<Pair<String, String>>?
/**
* Is true if the given database (and all its attached databases) pass integrity_check, false
* otherwise.
*/
- val isDatabaseIntegrityOk: Boolean
+ public val isDatabaseIntegrityOk: Boolean
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
index 90aee80..2be3a94 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteOpenHelper.android.kt
@@ -32,12 +32,12 @@
* create this and [Callback] to implement the methods that should be overridden.
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SupportSQLiteOpenHelper : Closeable {
+public interface SupportSQLiteOpenHelper : Closeable {
/**
* Return the name of the SQLite database being opened, as given to the constructor. `null`
* indicates an in-memory database.
*/
- val databaseName: String?
+ public val databaseName: String?
/**
* Enables or disables the use of write-ahead logging for the database.
@@ -49,7 +49,7 @@
*
* @param enabled True if write-ahead logging should be enabled, false if it should be disabled.
*/
- fun setWriteAheadLoggingEnabled(enabled: Boolean)
+ public fun setWriteAheadLoggingEnabled(enabled: Boolean)
/**
* Create and/or open a database that will be used for reading and writing. The first time this
@@ -67,7 +67,7 @@
* @return a read/write database object valid until [close] is called
* @throws SQLiteException if the database cannot be opened for writing
*/
- val writableDatabase: SupportSQLiteDatabase
+ public val writableDatabase: SupportSQLiteDatabase
/**
* Create and/or open a database. This will be the same object returned by [writableDatabase]
@@ -82,7 +82,7 @@
* @return a database object valid until [writableDatabase] or [close] is called.
* @throws SQLiteException if the database cannot be opened
*/
- val readableDatabase: SupportSQLiteDatabase
+ public val readableDatabase: SupportSQLiteDatabase
/** Close any open database object. */
override fun close()
@@ -93,13 +93,13 @@
* Handles various lifecycle events for the SQLite connection, similar to
* [room-runtime.SQLiteOpenHelper].
*/
- abstract class Callback(
+ public abstract class Callback(
/**
* Version number of the database (starting at 1); if the database is older,
* [Callback.onUpgrade] will be used to upgrade the database; if the database is newer,
* [Callback.onDowngrade] will be used to downgrade the database.
*/
- @JvmField val version: Int
+ @JvmField public val version: Int
) {
/**
* Called when the database connection is being configured, to enable features such as
@@ -117,7 +117,7 @@
*
* @param db The database.
*/
- open fun onConfigure(db: SupportSQLiteDatabase) {}
+ public open fun onConfigure(db: SupportSQLiteDatabase) {}
/**
* Called when the database is created for the first time. This is where the creation of
@@ -125,7 +125,7 @@
*
* @param db The database.
*/
- abstract fun onCreate(db: SupportSQLiteDatabase)
+ public abstract fun onCreate(db: SupportSQLiteDatabase)
/**
* Called when the database needs to be upgraded. The implementation should use this method
@@ -145,7 +145,7 @@
* @param oldVersion The old database version.
* @param newVersion The new database version.
*/
- abstract fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int)
+ public abstract fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int)
/**
* Called when the database needs to be downgraded. This is strictly similar to [onUpgrade]
@@ -160,7 +160,7 @@
* @param oldVersion The old database version.
* @param newVersion The new database version.
*/
- open fun onDowngrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
+ public open fun onDowngrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
throw SQLiteException(
"Can't downgrade database from version $oldVersion to $newVersion"
)
@@ -177,7 +177,7 @@
*
* @param db The database.
*/
- open fun onOpen(db: SupportSQLiteDatabase) {}
+ public open fun onOpen(db: SupportSQLiteDatabase) {}
/**
* The method invoked when database corruption is detected. Default implementation will
@@ -186,7 +186,7 @@
* @param db the [SupportSQLiteDatabase] object representing the database on which
* corruption is detected.
*/
- open fun onCorruption(db: SupportSQLiteDatabase) {
+ public open fun onCorruption(db: SupportSQLiteDatabase) {
// the following implementation is taken from {@link DefaultDatabaseErrorHandler}.
Log.e(TAG, "Corruption reported by sqlite on database: $db.path")
// is the corruption detected even before database could be 'opened'?
@@ -245,26 +245,26 @@
}
/** The configuration to create an SQLite open helper object using [Factory]. */
- class Configuration
+ public class Configuration
@Suppress("ExecutorRegistration") // For backwards compatibility
constructor(
/** Context to use to open or create the database. */
- @JvmField val context: Context,
+ @JvmField public val context: Context,
/** Name of the database file, or null for an in-memory database. */
- @JvmField val name: String?,
+ @JvmField public val name: String?,
/** The callback class to handle creation, upgrade and downgrade. */
- @JvmField val callback: Callback,
+ @JvmField public val callback: Callback,
/** If `true` the database will be stored in the no-backup directory. */
- @JvmField @Suppress("ListenerLast") val useNoBackupDirectory: Boolean = false,
+ @JvmField @Suppress("ListenerLast") public val useNoBackupDirectory: Boolean = false,
/**
* If `true` the database will be delete and its data loss in the case that it cannot be
* opened.
*/
- @JvmField @Suppress("ListenerLast") val allowDataLossOnRecovery: Boolean = false
+ @JvmField @Suppress("ListenerLast") public val allowDataLossOnRecovery: Boolean = false
) {
/** Builder class for [Configuration]. */
- open class Builder internal constructor(context: Context) {
+ public open class Builder internal constructor(context: Context) {
private val context: Context
private var name: String? = null
private var callback: Callback? = null
@@ -281,7 +281,7 @@
*
* @return The [Configuration] instance
*/
- open fun build(): Configuration {
+ public open fun build(): Configuration {
val callback = callback
requireNotNull(callback) { "Must set a callback to create the configuration." }
require(!useNoBackupDirectory || !name.isNullOrEmpty()) {
@@ -305,13 +305,15 @@
* @param name Name of the database file, or null for an in-memory database.
* @return This builder instance.
*/
- open fun name(name: String?): Builder = apply { this.name = name }
+ public open fun name(name: String?): Builder = apply { this.name = name }
/**
* @param callback The callback class to handle creation, upgrade and downgrade.
* @return This builder instance.
*/
- open fun callback(callback: Callback): Builder = apply { this.callback = callback }
+ public open fun callback(callback: Callback): Builder = apply {
+ this.callback = callback
+ }
/**
* Sets whether to use a no backup directory or not.
@@ -320,7 +322,7 @@
* no-backup directory.
* @return This builder instance.
*/
- open fun noBackupDirectory(useNoBackupDirectory: Boolean): Builder = apply {
+ public open fun noBackupDirectory(useNoBackupDirectory: Boolean): Builder = apply {
this.useNoBackupDirectory = useNoBackupDirectory
}
@@ -332,32 +334,33 @@
* case that it cannot be opened.
* @return this
*/
- open fun allowDataLossOnRecovery(allowDataLossOnRecovery: Boolean): Builder = apply {
- this.allowDataLossOnRecovery = allowDataLossOnRecovery
- }
+ public open fun allowDataLossOnRecovery(allowDataLossOnRecovery: Boolean): Builder =
+ apply {
+ this.allowDataLossOnRecovery = allowDataLossOnRecovery
+ }
}
- companion object {
+ public companion object {
/**
* Creates a new Configuration.Builder to create an instance of Configuration.
*
* @param context to use to open or create the database.
*/
@JvmStatic
- fun builder(context: Context): Builder {
+ public fun builder(context: Context): Builder {
return Builder(context)
}
}
}
/** Factory class to create instances of [SupportSQLiteOpenHelper] using [Configuration]. */
- fun interface Factory {
+ public fun interface Factory {
/**
* Creates an instance of [SupportSQLiteOpenHelper] using the given configuration.
*
* @param configuration The configuration to use while creating the open helper.
* @return A SupportSQLiteOpenHelper which can be used to open a database.
*/
- fun create(configuration: Configuration): SupportSQLiteOpenHelper
+ public fun create(configuration: Configuration): SupportSQLiteOpenHelper
}
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
index 9bff8c4..572879d 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteProgram.android.kt
@@ -19,14 +19,14 @@
/** An interface to map the behavior of [android.database.sqlite.SQLiteProgram]. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SupportSQLiteProgram : Closeable {
+public interface SupportSQLiteProgram : Closeable {
/**
* Bind a NULL value to this statement. The value remains bound until [.clearBindings] is
* called.
*
* @param index The 1-based index to the parameter to bind null to
*/
- fun bindNull(index: Int)
+ public fun bindNull(index: Int)
/**
* Bind a long value to this statement. The value remains bound until [clearBindings] is called.
@@ -35,7 +35,7 @@
* @param index The 1-based index to the parameter to bind
* @param value The value to bind
*/
- fun bindLong(index: Int, value: Long)
+ public fun bindLong(index: Int, value: Long)
/**
* Bind a double value to this statement. The value remains bound until [.clearBindings] is
@@ -44,7 +44,7 @@
* @param index The 1-based index to the parameter to bind
* @param value The value to bind
*/
- fun bindDouble(index: Int, value: Double)
+ public fun bindDouble(index: Int, value: Double)
/**
* Bind a String value to this statement. The value remains bound until [.clearBindings] is
@@ -53,7 +53,7 @@
* @param index The 1-based index to the parameter to bind
* @param value The value to bind, must not be null
*/
- fun bindString(index: Int, value: String)
+ public fun bindString(index: Int, value: String)
/**
* Bind a byte array value to this statement. The value remains bound until [.clearBindings] is
@@ -62,8 +62,8 @@
* @param index The 1-based index to the parameter to bind
* @param value The value to bind, must not be null
*/
- fun bindBlob(index: Int, value: ByteArray)
+ public fun bindBlob(index: Int, value: ByteArray)
/** Clears all existing bindings. Unset bindings are treated as NULL. */
- fun clearBindings()
+ public fun clearBindings()
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
index b5ffb7e..3db42f5 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQuery.android.kt
@@ -20,20 +20,20 @@
* [android.database.sqlite.SQLiteDatabase.rawQuery] because it allows binding type safe parameters.
*/
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SupportSQLiteQuery {
+public interface SupportSQLiteQuery {
/** The SQL query. This query can have placeholders(?) for bind arguments. */
- val sql: String
+ public val sql: String
/**
* Callback to bind the query parameters to the compiled statement.
*
* @param statement The compiled statement
*/
- fun bindTo(statement: SupportSQLiteProgram)
+ public fun bindTo(statement: SupportSQLiteProgram)
/**
* Is the number of arguments in this query. This is equal to the number of placeholders in the
* query string. See: https://www.sqlite.org/c3ref/bind_blob.html for details.
*/
- val argCount: Int
+ public val argCount: Int
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
index 60f5817..770820c 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteQueryBuilder.android.kt
@@ -19,7 +19,7 @@
/** A simple query builder to create SQL SELECT queries. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-class SupportSQLiteQueryBuilder private constructor(private val table: String) {
+public class SupportSQLiteQueryBuilder private constructor(private val table: String) {
private var distinct = false
private var columns: Array<out String>? = null
private var selection: String? = null
@@ -34,7 +34,7 @@
*
* @return this
*/
- fun distinct(): SupportSQLiteQueryBuilder = apply { this.distinct = true }
+ public fun distinct(): SupportSQLiteQueryBuilder = apply { this.distinct = true }
/**
* Sets the given list of columns as the columns that will be returned.
@@ -42,7 +42,7 @@
* @param columns The list of column names that should be returned.
* @return this
*/
- fun columns(columns: Array<out String>?): SupportSQLiteQueryBuilder = apply {
+ public fun columns(columns: Array<out String>?): SupportSQLiteQueryBuilder = apply {
this.columns = columns
}
@@ -53,11 +53,13 @@
* @param bindArgs The list of bind arguments to match against these columns
* @return this
*/
- fun selection(selection: String?, bindArgs: Array<out Any?>?): SupportSQLiteQueryBuilder =
- apply {
- this.selection = selection
- this.bindArgs = bindArgs
- }
+ public fun selection(
+ selection: String?,
+ bindArgs: Array<out Any?>?
+ ): SupportSQLiteQueryBuilder = apply {
+ this.selection = selection
+ this.bindArgs = bindArgs
+ }
/**
* Adds a GROUP BY statement.
@@ -65,7 +67,9 @@
* @param groupBy The value of the GROUP BY statement.
* @return this
*/
- fun groupBy(groupBy: String?): SupportSQLiteQueryBuilder = apply { this.groupBy = groupBy }
+ public fun groupBy(groupBy: String?): SupportSQLiteQueryBuilder = apply {
+ this.groupBy = groupBy
+ }
/**
* Adds a HAVING statement. You must also provide [groupBy] for this to work.
@@ -73,7 +77,7 @@
* @param having The having clause.
* @return this
*/
- fun having(having: String?): SupportSQLiteQueryBuilder = apply { this.having = having }
+ public fun having(having: String?): SupportSQLiteQueryBuilder = apply { this.having = having }
/**
* Adds an ORDER BY statement.
@@ -81,7 +85,9 @@
* @param orderBy The order clause.
* @return this
*/
- fun orderBy(orderBy: String?): SupportSQLiteQueryBuilder = apply { this.orderBy = orderBy }
+ public fun orderBy(orderBy: String?): SupportSQLiteQueryBuilder = apply {
+ this.orderBy = orderBy
+ }
/**
* Adds a LIMIT statement.
@@ -89,7 +95,7 @@
* @param limit The limit value.
* @return this
*/
- fun limit(limit: String): SupportSQLiteQueryBuilder = apply {
+ public fun limit(limit: String): SupportSQLiteQueryBuilder = apply {
val patternMatches = limitPattern.matcher(limit).matches()
require(limit.isEmpty() || patternMatches) { "invalid LIMIT clauses:$limit" }
this.limit = limit
@@ -100,7 +106,7 @@
*
* @return a new query
*/
- fun create(): SupportSQLiteQuery {
+ public fun create(): SupportSQLiteQuery {
require(!groupBy.isNullOrEmpty() || having.isNullOrEmpty()) {
"HAVING clauses are only permitted when using a groupBy clause"
}
@@ -146,7 +152,7 @@
append(' ')
}
- companion object {
+ public companion object {
private val limitPattern = Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?")
/**
@@ -156,7 +162,7 @@
* @return A builder to create a query.
*/
@JvmStatic
- fun builder(tableName: String): SupportSQLiteQueryBuilder {
+ public fun builder(tableName: String): SupportSQLiteQueryBuilder {
return SupportSQLiteQueryBuilder(tableName)
}
}
diff --git a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
index 829612c..a5c36ae 100644
--- a/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
+++ b/sqlite/sqlite/src/androidMain/kotlin/androidx/sqlite/db/SupportSQLiteStatement.android.kt
@@ -17,14 +17,14 @@
/** An interface to map the behavior of [android.database.sqlite.SQLiteStatement]. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SupportSQLiteStatement : SupportSQLiteProgram {
+public interface SupportSQLiteStatement : SupportSQLiteProgram {
/**
* Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
* CREATE / DROP table, view, trigger, index etc.
*
* @throws [android.database.SQLException] If the SQL string is invalid for some reason
*/
- fun execute()
+ public fun execute()
/**
* Execute this SQL statement, if the the number of rows affected by execution of this SQL
@@ -33,7 +33,7 @@
* @return the number of rows affected by this SQL statement execution.
* @throws [android.database.SQLException] If the SQL string is invalid for some reason
*/
- fun executeUpdateDelete(): Int
+ public fun executeUpdateDelete(): Int
/**
* Execute this SQL statement and return the ID of the row inserted due to this call. The SQL
@@ -42,7 +42,7 @@
* @return the row ID of the last row inserted, if this insert is successful. -1 otherwise.
* @throws [android.database.SQLException] If the SQL string is invalid for some reason
*/
- fun executeInsert(): Long
+ public fun executeInsert(): Long
/**
* Execute a statement that returns a 1 by 1 table with a numeric value. For example, SELECT
@@ -51,7 +51,7 @@
* @return The result of the query.
* @throws [android.database.sqlite.SQLiteDoneException] if the query returns zero rows
*/
- fun simpleQueryForLong(): Long
+ public fun simpleQueryForLong(): Long
/**
* Execute a statement that returns a 1 by 1 table with a text value. For example, SELECT
@@ -60,5 +60,5 @@
* @return The result of the query.
* @throws [android.database.sqlite.SQLiteDoneException] if the query returns zero rows
*/
- fun simpleQueryForString(): String?
+ public fun simpleQueryForString(): String?
}
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
index b997417..f930e84 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLite.kt
@@ -22,14 +22,14 @@
/** Executes a single SQL statement that returns no values. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-fun SQLiteConnection.execSQL(sql: String) {
+public fun SQLiteConnection.execSQL(sql: String) {
prepare(sql).use { it.step() }
}
/** Use the receiver statement within the [block] and closes it once it is done. */
// TODO(b/315461431): Migrate to a Closeable interface in KMP
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-inline fun <R> SQLiteStatement.use(block: (SQLiteStatement) -> R): R {
+public inline fun <R> SQLiteStatement.use(block: (SQLiteStatement) -> R): R {
try {
return block.invoke(this)
} finally {
@@ -39,7 +39,7 @@
/** Throws a [SQLiteException] with its message formed by the given [errorCode] amd [errorMsg]. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-fun throwSQLiteException(errorCode: Int, errorMsg: String?): Nothing {
+public fun throwSQLiteException(errorCode: Int, errorMsg: String?): Nothing {
val message = buildString {
append("Error code: $errorCode")
if (errorMsg != null) {
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
index 5922ca2..128ef24 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteConnection.kt
@@ -26,7 +26,7 @@
*/
// TODO(b/315461431): No common Closeable interface in KMP
@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
-interface SQLiteConnection {
+public interface SQLiteConnection {
/**
* Prepares a new SQL statement.
*
@@ -35,7 +35,7 @@
* @param sql the SQL statement to prepare
* @return the prepared statement.
*/
- fun prepare(sql: String): SQLiteStatement
+ public fun prepare(sql: String): SQLiteStatement
/**
* Closes the database connection.
@@ -43,5 +43,5 @@
* Once a connection is closed it should no longer be used. Calling this function on an already
* closed database connection is a no-op.
*/
- fun close()
+ public fun close()
}
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
index a0fa75c..5cb23bf 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteDriver.kt
@@ -18,12 +18,12 @@
/** An interface to open database connections. */
@Suppress("AcronymName") // SQL is a known term and should remain capitalized
-interface SQLiteDriver {
+public interface SQLiteDriver {
/**
* Opens a new database connection.
*
* @param fileName Name of the database file.
* @return the database connection.
*/
- fun open(fileName: String): SQLiteConnection
+ public fun open(fileName: String): SQLiteConnection
}
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteException.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteException.kt
index 1276395..c2d575e 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteException.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteException.kt
@@ -23,6 +23,6 @@
*
* See [Result and Error codes](https://www.sqlite.org/rescode.html)
*/
-expect class SQLiteException
+public expect class SQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
constructor(message: String) : RuntimeException
diff --git a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
index 039d211..65ba44c 100644
--- a/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
+++ b/sqlite/sqlite/src/commonMain/kotlin/androidx/sqlite/SQLiteStatement.kt
@@ -26,14 +26,14 @@
*/
// TODO(b/315461431): No common Closeable interface in KMP
@Suppress("NotCloseable", "AcronymName") // SQL is a known term and should remain capitalized
-interface SQLiteStatement {
+public interface SQLiteStatement {
/**
* Binds a ByteArray value to this statement at an index.
*
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindBlob(index: Int, value: ByteArray)
+ public fun bindBlob(index: Int, value: ByteArray)
/**
* Binds a Double value to this statement at an index.
@@ -41,7 +41,7 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindDouble(index: Int, value: Double)
+ public fun bindDouble(index: Int, value: Double)
/**
* Binds a Float value to this statement at an index.
@@ -49,7 +49,7 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindFloat(index: Int, value: Float) {
+ public fun bindFloat(index: Int, value: Float) {
bindDouble(index, value.toDouble())
}
@@ -59,7 +59,7 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindLong(index: Int, value: Long)
+ public fun bindLong(index: Int, value: Long)
/**
* Binds a Int value to this statement at an index.
@@ -67,7 +67,7 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindInt(index: Int, value: Int) {
+ public fun bindInt(index: Int, value: Int) {
bindLong(index, value.toLong())
}
@@ -77,7 +77,7 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindBoolean(index: Int, value: Boolean) {
+ public fun bindBoolean(index: Int, value: Boolean) {
bindLong(index, if (value) 1L else 0L)
}
@@ -87,14 +87,14 @@
* @param index the 1-based index of the parameter to bind
* @param value the value to bind
*/
- fun bindText(index: Int, value: String)
+ public fun bindText(index: Int, value: String)
/**
* Binds a NULL value to this statement at an index.
*
* @param index the 1-based index of the parameter to bind
*/
- fun bindNull(index: Int)
+ public fun bindNull(index: Int)
/**
* Returns the value of the column at [index] as a ByteArray.
@@ -102,7 +102,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getBlob(index: Int): ByteArray
+ public fun getBlob(index: Int): ByteArray
/**
* Returns the value of the column at [index] as a Double.
@@ -110,7 +110,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getDouble(index: Int): Double
+ public fun getDouble(index: Int): Double
/**
* Returns the value of the column at [index] as a Float.
@@ -118,7 +118,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getFloat(index: Int): Float {
+ public fun getFloat(index: Int): Float {
return getDouble(index).toFloat()
}
@@ -128,7 +128,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getLong(index: Int): Long
+ public fun getLong(index: Int): Long
/**
* Returns the value of the column at [index] as a Int.
@@ -136,7 +136,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getInt(index: Int): Int {
+ public fun getInt(index: Int): Int {
return getLong(index).toInt()
}
@@ -146,7 +146,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getBoolean(index: Int): Boolean {
+ public fun getBoolean(index: Int): Boolean {
return getLong(index) != 0L
}
@@ -156,7 +156,7 @@
* @param index the 0-based index of the column
* @return the value of the column
*/
- fun getText(index: Int): String
+ public fun getText(index: Int): String
/**
* Returns true if the value of the column at [index] is NULL.
@@ -164,14 +164,14 @@
* @param index the 0-based index of the column
* @return true if the column value is NULL, false otherwise
*/
- fun isNull(index: Int): Boolean
+ public fun isNull(index: Int): Boolean
/**
* Returns the number of columns in the result of the statement.
*
* @return the number of columns
*/
- fun getColumnCount(): Int
+ public fun getColumnCount(): Int
/**
* Returns the name of a column at [index] in the result of the statement.
@@ -179,14 +179,14 @@
* @param index the 0-based index of the column
* @return the name of the column
*/
- fun getColumnName(index: Int): String
+ public fun getColumnName(index: Int): String
/**
* Returns the name of the columns in the result of the statement ordered by their index.
*
* @return the names of the columns
*/
- fun getColumnNames(): List<String> {
+ public fun getColumnNames(): List<String> {
return List(getColumnCount()) { i -> getColumnName(i) }
}
@@ -199,16 +199,16 @@
*
* @return true if there are more rows to evaluate or false if the statement is done executing
*/
- fun step(): Boolean
+ public fun step(): Boolean
/**
* Resets the prepared statement back to initial state so that it can be re-executed via [step].
* Any parameter bound via the bind*() APIs will retain their value.
*/
- fun reset()
+ public fun reset()
/** Clears all parameter bindings. Unset bindings are treated as NULL. */
- fun clearBindings()
+ public fun clearBindings()
/**
* Closes the statement.
@@ -216,5 +216,5 @@
* Once a statement is closed it should no longer be used. Calling this function on an already
* closed statement is a no-op.
*/
- fun close()
+ public fun close()
}
diff --git a/sqlite/sqlite/src/jvmMain/kotlin/androidx/sqlite/SQLiteException.jvm.kt b/sqlite/sqlite/src/jvmMain/kotlin/androidx/sqlite/SQLiteException.jvm.kt
index cf6e78c..a3f49cb 100644
--- a/sqlite/sqlite/src/jvmMain/kotlin/androidx/sqlite/SQLiteException.jvm.kt
+++ b/sqlite/sqlite/src/jvmMain/kotlin/androidx/sqlite/SQLiteException.jvm.kt
@@ -18,6 +18,6 @@
import androidx.annotation.RestrictTo
-actual class SQLiteException
+public actual class SQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
actual constructor(message: String) : RuntimeException(message)
diff --git a/sqlite/sqlite/src/nativeMain/kotlin/androidx/sqlite/SQLiteException.native.kt b/sqlite/sqlite/src/nativeMain/kotlin/androidx/sqlite/SQLiteException.native.kt
index cf6e78c..a3f49cb 100644
--- a/sqlite/sqlite/src/nativeMain/kotlin/androidx/sqlite/SQLiteException.native.kt
+++ b/sqlite/sqlite/src/nativeMain/kotlin/androidx/sqlite/SQLiteException.native.kt
@@ -18,6 +18,6 @@
import androidx.annotation.RestrictTo
-actual class SQLiteException
+public actual class SQLiteException
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
actual constructor(message: String) : RuntimeException(message)
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeScreenshotTest.kt
new file mode 100644
index 0000000..df52e66
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeScreenshotTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2024 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 androidx.wear.compose.material3
+
+import android.os.Build
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.shape.AbsoluteCutCornerShape
+import androidx.compose.foundation.shape.AbsoluteRoundedCornerShape
+import androidx.compose.foundation.shape.CutCornerShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.screenshot.AndroidXScreenshotTestRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+class AnimatedCornerShapeScreenshotTest {
+
+ @get:Rule val rule = createComposeRule()
+
+ @get:Rule val screenshotRule = AndroidXScreenshotTestRule(SCREENSHOT_GOLDEN_PATH)
+
+ @get:Rule val testName = TestName()
+
+ @Test
+ fun cutCornerShapeLtr() = verifyScreenshot {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ CutCornerShape(topStart = 2.dp, topEnd = 4.dp, bottomEnd = 6.dp, bottomStart = 8.dp)
+ ) {}
+ }
+
+ @Test
+ fun cutCornerShapeRtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ CutCornerShape(
+ topStart = 2.dp,
+ topEnd = 4.dp,
+ bottomEnd = 6.dp,
+ bottomStart = 8.dp
+ )
+ ) {}
+ }
+
+ @Test
+ fun absoluteCutCornerShapeLtr() = verifyScreenshot {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ AbsoluteCutCornerShape(
+ topLeft = 2.dp,
+ topRight = 4.dp,
+ bottomRight = 6.dp,
+ bottomLeft = 8.dp
+ )
+ ) {}
+ }
+
+ @Test
+ fun absoluteCutCornerShapeRtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ AbsoluteCutCornerShape(
+ topLeft = 2.dp,
+ topRight = 4.dp,
+ bottomRight = 6.dp,
+ bottomLeft = 8.dp
+ )
+ ) {}
+ }
+
+ @Test
+ fun absoluteRoundedCornerShapeLtr() = verifyScreenshot {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ AbsoluteRoundedCornerShape(
+ topLeft = 2.dp,
+ topRight = 4.dp,
+ bottomRight = 6.dp,
+ bottomLeft = 8.dp
+ )
+ ) {}
+ }
+
+ @Test
+ fun absoluteRoundedCornerShapeRtl() =
+ verifyScreenshot(layoutDirection = LayoutDirection.Rtl) {
+ FilledIconButton(
+ onClick = {},
+ shape =
+ AbsoluteRoundedCornerShape(
+ topLeft = 2.dp,
+ topRight = 4.dp,
+ bottomRight = 6.dp,
+ bottomLeft = 8.dp
+ )
+ ) {}
+ }
+
+ private fun verifyScreenshot(
+ layoutDirection: LayoutDirection = LayoutDirection.Ltr,
+ content: @Composable () -> Unit
+ ) {
+ rule.setContentWithTheme {
+ CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
+ Box(modifier = Modifier.background(Color.Black).testTag(TEST_TAG)) { content() }
+ }
+ }
+
+ rule
+ .onNodeWithTag(TEST_TAG)
+ .captureToImage()
+ .assertAgainstGolden(screenshotRule, testName.methodName)
+ }
+}
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeTest.kt
new file mode 100644
index 0000000..5886659
--- /dev/null
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/AnimatedCornerShapeTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2024 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 androidx.wear.compose.material3
+
+import androidx.compose.foundation.shape.AbsoluteCutCornerShape
+import androidx.compose.foundation.shape.AbsoluteRoundedCornerShape
+import androidx.compose.foundation.shape.CutCornerShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+
+class AnimatedCornerShapeTest {
+ @get:Rule val rule = createComposeRule()
+
+ @Test
+ fun convertsRoundedCornerShape() {
+ val roundedCornerShape = RoundedCornerShape(10.dp)
+
+ val roundedPolygon =
+ roundedCornerShape.toRoundedPolygonOrNull(
+ size = Size(100f, 100f),
+ density = Density(density = 2f),
+ layoutDirection = LayoutDirection.Ltr
+ )
+
+ assertThat(roundedPolygon).isNotNull()
+ assertThat(roundedPolygon!!.calculateBounds()).isEqualTo(floatArrayOf(0f, 0f, 1f, 1f))
+ assertThat(roundedPolygon.cubics.size).isEqualTo(9)
+
+ val points =
+ roundedPolygon.cubics.flatMap {
+ listOf(Offset(it.anchor0X, it.anchor0Y), Offset(it.anchor1X, it.anchor1Y))
+ }
+ assertThat(points)
+ .containsAtLeast(
+ Offset(1.0f, 0.8f),
+ Offset(0.8f, 1.0f),
+ Offset(0.2f, 1.0f),
+ Offset(0.0f, 0.8f),
+ Offset(0.0f, 0.2f),
+ Offset(0.2f, 0.0f),
+ Offset(0.8f, 0.0f),
+ Offset(1.0f, 0.2f),
+ )
+ }
+
+ @Test
+ fun convertsCutCornerShape() {
+ val cutCornerShape = CutCornerShape(10.dp)
+
+ val roundedPolygon =
+ cutCornerShape.toRoundedPolygonOrNull(
+ size = Size(100f, 100f),
+ density = Density(density = 2f),
+ layoutDirection = LayoutDirection.Ltr
+ )
+
+ assertThat(roundedPolygon).isNotNull()
+ assertThat(roundedPolygon!!.calculateBounds()).isEqualTo(floatArrayOf(0f, 0f, 1f, 1f))
+ assertThat(roundedPolygon.cubics.size).isEqualTo(8)
+
+ val points =
+ roundedPolygon.cubics.flatMap {
+ listOf(Offset(it.anchor0X, it.anchor0Y), Offset(it.anchor1X, it.anchor1Y))
+ }
+ assertThat(points)
+ .containsAtLeast(
+ Offset(1.0f, 0.8f),
+ Offset(0.8f, 1.0f),
+ Offset(0.2f, 1.0f),
+ Offset(0.0f, 0.8f),
+ Offset(0.0f, 0.2f),
+ Offset(0.2f, 0.0f),
+ Offset(0.8f, 0.0f),
+ Offset(1.0f, 0.2f),
+ )
+ }
+
+ @Test
+ fun convertsAbsoluteRoundedCornerShape() {
+ val roundedCornerShape = AbsoluteRoundedCornerShape(5.dp)
+
+ val roundedPolygon =
+ roundedCornerShape.toRoundedPolygonOrNull(
+ size = Size(100f, 100f),
+ density = Density(density = 2f),
+ layoutDirection = LayoutDirection.Ltr
+ )
+
+ assertThat(roundedPolygon).isNotNull()
+ assertThat(roundedPolygon!!.calculateBounds()).isEqualTo(floatArrayOf(0f, 0f, 1f, 1f))
+ assertThat(roundedPolygon.cubics.size).isEqualTo(9)
+
+ val points =
+ roundedPolygon.cubics.flatMap {
+ listOf(Offset(it.anchor0X, it.anchor0Y), Offset(it.anchor1X, it.anchor1Y))
+ }
+ assertThat(points)
+ .containsAtLeast(
+ Offset(1.0f, 0.9f),
+ Offset(0.9f, 1.0f),
+ Offset(0.1f, 1.0f),
+ Offset(0.0f, 0.9f),
+ Offset(0.0f, 0.1f),
+ Offset(0.1f, 0.0f),
+ Offset(0.9f, 0.0f),
+ Offset(1.0f, 0.1f),
+ )
+ }
+
+ @Test
+ fun convertsAbsoluteCutCornerShape() {
+ val cutCornerShape = AbsoluteCutCornerShape(5.dp)
+
+ val roundedPolygon =
+ cutCornerShape.toRoundedPolygonOrNull(
+ size = Size(100f, 100f),
+ density = Density(density = 2f),
+ layoutDirection = LayoutDirection.Ltr
+ )
+
+ assertThat(roundedPolygon).isNotNull()
+ assertThat(roundedPolygon!!.calculateBounds()).isEqualTo(floatArrayOf(0f, 0f, 1f, 1f))
+ assertThat(roundedPolygon.cubics.size).isEqualTo(8)
+
+ val points =
+ roundedPolygon.cubics.flatMap {
+ listOf(Offset(it.anchor0X, it.anchor0Y), Offset(it.anchor1X, it.anchor1Y))
+ }
+ assertThat(points)
+ .containsAtLeast(
+ Offset(1.0f, 0.9f),
+ Offset(0.9f, 1.0f),
+ Offset(0.1f, 1.0f),
+ Offset(0.0f, 0.9f),
+ Offset(0.0f, 0.1f),
+ Offset(0.1f, 0.0f),
+ Offset(0.9f, 0.0f),
+ Offset(1.0f, 0.1f),
+ )
+ }
+}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedCornerShape.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedCornerShape.kt
index 70fa44b..afca2cd 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedCornerShape.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimatedCornerShape.kt
@@ -170,7 +170,7 @@
* @param size The size of the final Composable such as a Button.
* @param density The density of the composition.
*/
-private fun CornerBasedShape.toRoundedPolygonOrNull(
+internal fun CornerBasedShape.toRoundedPolygonOrNull(
size: Size,
density: Density,
layoutDirection: LayoutDirection